1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-10-11 04:37:39 +00:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Alexander Barton
c45d9dd1f0 ngIRCd Release 20.2 2013-02-15 12:18:02 +01:00
Sebastian Köhler
b3d4cf9081 KICK: Fix denial of service bug
Test if the user that it is to be kicked is on the channel before user
channel modes are tested. Otherwise assert( cl2chan != NULL ); in
line 742 would fail and stop the service.
(cherry picked from commit 0e63fb3fa7)
2013-02-15 11:56:24 +01:00
Alexander Barton
1265eb15b8 "WHO <hostmask>": use displayed hostname for matching
Use the currently "displayed hostname" (which can be cloaked!) for
hostname matching, not the real one. In other words: don't display
all the cloaked users on a specific real hostname!

Thanks to DNS <dns@rbose.org> for reporting this issue.
(cherry picked from commit 1e8b775a7a)
2013-02-13 22:12:09 +01:00
Alexander Barton
84612fe773 autogen.sh: Don't use "egrep -o", use "sed"
"egrep -o" isn't portable and not available on OpenBSD, for example. So
let's use sed instead to get the automake version. The expression used
now is less specific but should work as well ...
(cherry picked from commit 419ff38a07)
2013-02-13 22:11:49 +01:00
Alexander Barton
84f5839c17 configure: "netinet/in_systm.h" is optional
The header file "netinet/in_systm.h" already is optional in ngIRCd, so
don't require it in the configure script. Now ngIRCd can be built on
Minix 3 again :-)
(cherry picked from commit fd260404ca)
2013-02-13 22:11:39 +01:00
Alexander Barton
cb3b411166 Return better "Connection not registered as server link" errors
Now ngIRCd returns a more specific error message for numeric
ERR_NOTREGISTERED(451) when a regular user tries to use a command that
isn't allowed for users but for servers: ERR_NOTREGISTEREDSERVER(451).
(cherry picked from commit 508ca3044d)
2013-02-13 22:11:23 +01:00
Alexander Barton
121bcacb98 MODE: don't report error on "more modes than parameters"
Don't report ERR_NEEDMOREPARAMS(461) when a MDOE command with more modes
than nicknames is handled, as well as for channel limit and key changes
without specifying the limit or key parameters.

This is how a lot (all?) other IRC servers behave, including ircd2.11,
InspIRCd, and ircd-seven. And because of clients (tested with Textual and
mIRC) sending bogus MODE commands like "MODE -ooo nick", end-users got the
expected result as well as correct but misleading error messages ...

If ngIRCd is compiled using "strict mode", these errors are still reported.

Reported-by: Tim <tim@stackwatch.net>
(cherry picked from commit d8f2964710)
2013-02-13 22:11:14 +01:00
Alexander Barton
4105635566 Correctly detect when SSL subsystem must be initialized
This patch introduces the new function Conf_SSLInUse() to check when the
current server configuration requires the SSL subsystem to be initialized
and accounts incoming as well as outgoing connections -- so this fixes
commit bb20aeb9 ("Initialize SSL when needed only, and disable SSL on
errors") which only handled the inbound case  ...

Tested-by: Brett Smith <brett@w3.org>
(cherry picked from commit ab00997698)
2013-02-13 22:11:05 +01:00
Alexander Barton
90fce2ed16 autogen.sh: Enforce serial test harness on automake >=1.13
(cherry picked from commit 0703fcd719)
2013-02-13 22:10:49 +01:00
93 changed files with 3155 additions and 5385 deletions

1
.gitignore vendored
View File

@@ -7,7 +7,6 @@ ansi2knr.h
ar-lib ar-lib
autom4te.cache autom4te.cache
build-stamp-ngircd* build-stamp-ngircd*
compile
config.log config.log
config.status config.status
configure configure

View File

@@ -1,8 +0,0 @@
language: c
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq libident-dev libpam0g-dev libssl-dev libwrap0-dev zlib1g-dev expect telnet
compiler:
- gcc
- clang
script: ./autogen.sh && ./configure --enable-ipv6 --with-iconv --with-ident --with-openssl --with-pam --with-tcp-wrappers --with-zlib && make check

44
AUTHORS
View File

@@ -18,41 +18,29 @@ Don't mail the people listed here directly, if possible!
Main Authors Main Authors
~~~~~~~~~~~~ ~~~~~~~~~~~~
Alexander Barton <alex@barton.de> Alexander Barton, <alex@barton.de> (alex)
Florian Westphal <fw@strlen.de> Florian Westphal, <fw@strlen.de>
Contributors Contributors
~~~~~~~~~~~~ ~~~~~~~~~~~~
Ali Shemiran <ashemira@ucsd.edu> Ali Shemiran, <ashemira@ucsd.edu>
Ask Bjørn Hansen <ask@develooper.com> Ask Bjørn Hansen, <ask@develooper.com>
Benjamin Pineau <ben@zouh.org> Benjamin Pineau, <ben@zouh.org>
Brandon Beresini <beresini@google.com> Brandon Beresini, <beresini@google.com>
Brett Smith <brett@w3.org> Bryan Caldwell, <bcaldwel@ucsd.edu>
Brian Collins <bricollins@gmail.com> Dana Dahlstrom, <dana+ngIRCd@cs.ucsd.edu>
Bryan Caldwell <bcaldwel@ucsd.edu> Eric Grunow, <egrunow@ucsd.edu>
Christoph Biedl <ngircd.anoy@manchmal.in-ulm.de> Goetz Hoffart, <goetz@hoffart.de>
DNS <dns@rbose.org> Ilja Osthoff, <i.osthoff@gmx.net>
Dana Dahlstrom <dana+ngIRCd@cs.ucsd.edu> Jari Aalto, <jari.aalto@cante.net>
David Kingston <deathking1337@aim.com> Rolf Eike Beer, <eike@sf-mail.de>
Eric Grunow <egrunow@ucsd.edu> Scott Perry, <scperry@ucsd.edu>
Federico G. Schwindt <fgsch@lodoss.net> Sean Reifschneider, <jafo-rpms@tummy.com>
Gabor Adam Toth <tg@tgbit.net>
Goetz Hoffart <goetz@hoffart.de>
Ilja Osthoff <i.osthoff@gmx.net>
Jari Aalto <jari.aalto@cante.net>
Neale Pickett <neale@woozle.org>
Rolf Eike Beer <eike@sf-mail.de>
Scott Perry <scperry@ucsd.edu>
Sean Reifschneider <jafo-rpms@tummy.com>
Sebastian Köhler <sebkoehler@whoami.org.uk>
Tassilo Schweyer <dev@welterde.de>
William Pitcock <nenolod@dereferenced.org>
xor <xorboy@gmail.com>
Code snippets Code snippets
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
J. Kercheval: pattern matching functions J. Kercheval: pattern matching functions
Patrick Powell <papowell@astart.com>: snprintf()-function Patrick Powell, <papowell@astart.com>: snprintf()-function
Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions

158
ChangeLog
View File

@@ -9,162 +9,10 @@
-- ChangeLog -- -- ChangeLog --
ngIRCd 21~rc2 (2013-10-20)
- Report the correct configuration file name on configuration errors,
support longer configuration lines, and warn when lines are truncated.
- Use arc4random() function to generate "random" numbers, when available.
- platformtest.sh: Detect clang compiler, and clean up GIT source tree
before building (when possible).
- Update (date of) manual pages.
- Update "Upgrade Information" in INSTALL file, add more systems to
doc/Platforms.txt, and fix spelling in NEWS and ChangeLog files =:)
- Fix remaining compiler warnings on OpenBSD.
ngIRCd 21~rc1 (2013-10-05)
- Actually KILL clients on GLINE/KLINE. (Closes bug #156)
- Adjust log messages for invalid and spoofed prefixes, which cleans up
logging of commands related to already KILL'ed clients. And don't
forward KILL commands for (already) unknown clients any more to prevent
unnecessary duplicates.
- Add support to show all user links using the "STATS L" (uppercase)
command (restricted to IRC Operators).
- Fixed blocking of server reconnects in some error configurations.
- Don't ignore SSL-related errors during startup any more: abort startup
when SSL is requested by the configuration but can't be initialized and
don't continue only listening on plain text communication ports.
(Closes bug #163)
- Implement configurable SSL cipher list selection for GnuTLS and OpenSSL
using the new configuration option "CipherList". In addition, this
changes the defaults to more secure values: "HIGH:!aNULL:@STRENGTH" for
OpenSSL, and "SECURE128" for GnuTLS.
- Fix "TRACE": Correctly return ERR_NEEDMOREPARAMS(461) (which basically
is "syntax error") when there are too many parameters.
- Clean up lots of permission and parameter checks in functions handling
IRC commands; and more consistently add penalty times on errors.
- Fix error numeric of WHOIS when no nick name has been provided:
as per RFC it should be ERR_NONICKNAMEGIVEN(431).
- Only log "IDENT ... no result" messages when an IDENT looked took place
and didn't return any data, not when IDENT has been disabled.
- Show connection flag "s" (SSL) in RPL_TRACE{LINK|SERVER} messages: now
you can check if a server-to-server link is SSL-encrypted or not using
the IRC "TRACE" command.
- Correctly discard supplementary groups on server startup.
- Save client IP address text for "WebIRC" users and correctly display
it on WHOIS, for example. (Closes bug #159)
- Implement the new configuration option "DefaultUserModes" which lists
user modes that become automatically set on new local clients right
after login. Please note that only modes can be set that the client
could set on itself, so you can't set "a" (away) or "o" (IRC Op),
for example! User modes "i" (invisible) or "x" (cloaked) etc. are
"interesting", though. (Closes bug #160)
- Add support for the new METADATA "account" property, which allows
services to automatically identify users after netsplits and across
service restarts.
- Enforce "penalty times" on error conditions more consistently and in
more places. Now most error codes sent back from the IRC server to the
client should result in a 2 second "penalty".
- Implement a new configuration option "AllowedChannelTypes" that lists
all allowed channel types (channel prefixes) for newly created channels
on the local server. By default, all supported channel types are allowed.
If set to the empty string, local clients can't create new channels at
all, which equals the old "PredefChannelsOnly = yes" setting.
This change deprecates the "PredefChannelsOnly" variable, too, but it is
still supported and translated to the appropriate "AllowedChannelTypes"
setting. When the old "PredefChannelsOnly" variable is processed, a
warning message is logged. (Closes bug #152)
- Add support for "client certificate fingerprinting". When a client
passes an SSL certificate to the server, the "fingerprint" will be
forwarded in the network which enables IRC services to identify the
user using this certificate and not using passwords.
- IRC Operator names, as defined in ngircd.conf, are logged now when
handling successful OPER commands.
- Some error conditions while handling IRC commands, like "permission
denied" or "need more parameters", result in more penalty times.
- The numeric replies of some commands became split too early which
resulted in more numeric reply lines than necessary.
- Implement a new configuration option "IncludeDir" in the "[Options]"
section that can be used to specify a directory which can contain
further configuration files and configuration file snippets matching
the pattern "*.conf". These files are read in after the main server
configuration file ("ngircd.conf" by default) has been read in and
parsed. The default is "$SYSCONFDIR/ngircd.conf.d", so that it is
possible to adjust the configuration only by placing additional files
into this directory. (Closes bug #157)
- Fix use-after-free in the Lists_CheckReason() function, which is used
to check if a client is a member of a particular ban/invite/... list.
- Xcode: fix detection of host OS, vendor, and CPU type, and update
project settings for Xcode 5.
- OS X PackageMaker: use relative path names in project files and package
with correct file permissions (requires root privileges on "make").
- Add Travis-CI configuration file (".travis.yml") to project.
- Look for possible cloaked Masks in Lists. Users with +x user mode can
be banned with their cloaked hostname now.
- Don't read SSL client data before DNS resolver is finished which could
have resulted in discarding the resolved client hostname and IDENT
reply afterwards, because in some situations (timing dependent) the
NICK and USER commands could have already been read in from the client,
stored in the buffer, and been processed.
Thanks to Julian Brost for reporting the issue and testing, and to
Federico G. Schwindt <fgsch@lodoss.net> for helping to debug it!
- Increase password length limit to 64 characters. (Closes bug #154)
- doc/Services.txt: Update Anope status and URL.
- Clean up Xcode project file, remove outdated files, add missing ones.
- Update Doxygen configuration file.
- configure: search for iconv_open as well as libiconv_open, because
on some installations iconv_open() is actually libiconv_open().
iconv_open() is the glibc version while libiconv_open() is the
libiconv version, now both variants are supported. (Closes bug #151)
- ngIRCd now accepts user names including "@" characters, saves the
unmodified name for authentication but stores only the part in front
of the "@" character as "IRC user name". And the latter is how
ircd2.11, Bahamut, and irc-seven behave as well. (Closes bug #155)
- Lots of IRC "information functions" like ADMIN, INFO, ... now accept
server masks and names of connected users (in addition to server names)
for specifying the target server of the command. (Closes bug #153)
- Implement a new configuration option "IdleTimeout" in the "[Limits]"
section of the configuration file which can be used to set a timeout
in seconds after which the whole daemon will shutdown when no more
connections are left active after handling at least one client.
The default is 0, "never".
This can be useful for testing or when ngIRCd is started using "socket
activation" with systemd(8), for example.
- Implement support for systemd(8) "socket activation".
- contrib/README: add description for more files.
- Enable WHOIS to display information about IRC Services using the new
numeric 310(RPL_WHOISSERVICE) This numeric is used for this purpose by
InspIRCd, for example -- but as usual, other numerics are in use, too,
like 613 in UltimateIRCd ...
Please note that neither the Operator (+o) not the "bot status" (+B)
of an IRC service is displayed in the output.
- Exit message: use singular & plural :-)
- autogen.sh: Check for autoconf/automake wrapper scripts
- Add missing punctuation marks in log messages, adjust some severity
levels, and make SSL-related messages more readable.
- AUTHORS file: Update list of contributors.
- Update systemd(8) example configuration files in ./contrib/ directory:
the "ngircd.service" file now uses the "forking" service type which
enhances the log messages shown by "systemctl status ngircd.service",
and the new "ngircd.socket" file configures a systemd socket that
configures a socket for ngIRCd and launches the daemon on demand.
- Enhance help system and the HELP command: now a "help text file" can be
set using the new configuration option "HelpFile" ("global" section),
which is read in and parsed on server startup and configuration reload,
and then is used to output individual help texts to specific topics.
Please see the file ./doc/Commands.txt for details.
ngIRCd 20.3 (2013-08-23)
- Security: Fix a denial of service bug (server crash) which could happen
when the configuration option "NoticeAuth" is enabled (which is NOT the
default) and ngIRCd failed to send the "notice auth" messages to new
clients connecting to the server (CVE-2013-5580).
ngIRCd 20.2 (2013-02-15) ngIRCd 20.2 (2013-02-15)
- Security: Fix a denial of service bug in the function handling KICK - Security: Fix a denial of service bug in the function handling KICK
commands that could be used by arbitrary users to to crash the daemon commands that could be used by arbitrary users to to crash the daemon.
(CVE-2013-1747).
- WHO command: Use the currently "displayed hostname" (which can be cloaked!) - WHO command: Use the currently "displayed hostname" (which can be cloaked!)
for hostname matching, not the real one. In other words: don't display all for hostname matching, not the real one. In other words: don't display all
the cloaked users on a specific real hostname! the cloaked users on a specific real hostname!
@@ -187,7 +35,7 @@ ngIRCd 20.2 (2013-02-15)
- autogen.sh: Enforce serial test harness on GNU automake >=1.13. The - autogen.sh: Enforce serial test harness on GNU automake >=1.13. The
new parallel test harness which is enabled by default starting with new parallel test harness which is enabled by default starting with
automake 1.13 isn't compatible with our test suite. automake 1.13 isn't compatible with our test suite.
And don't use "egrep -o", instead use "sed", because it isn't portable And don't use "egrep -o", insetead use "sed", because it isn't portable
and not available on OpenBSD, for example. and not available on OpenBSD, for example.
ngIRCd 20.1 (2013-01-02) ngIRCd 20.1 (2013-01-02)
@@ -208,7 +56,7 @@ ngIRCd 20 (2012-12-17)
- Allow user names ("INDENT") up to 20 characters when ngIRCd has not - Allow user names ("INDENT") up to 20 characters when ngIRCd has not
been configured for "strict RFC mode". This is useful if you are using been configured for "strict RFC mode". This is useful if you are using
external (PAM) authentication mechanisms that require longer user names. external (PAM) authenticaion mechanisms that require longer user names.
Patch suggested by Brett Smith <brett@w3.org>, see Patch suggested by Brett Smith <brett@w3.org>, see
<http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>. <http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>.

13
INSTALL
View File

@@ -12,22 +12,11 @@
I. Upgrade Information I. Upgrade Information
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
Differences to version 20.x
- Starting with ngIRCd 21, the ciphers used by SSL are configurable and
default to HIGH:!aNULL:@STRENGTH (OpenSSL) or SECURE128 (GnuTLS).
Previous version were using the OpenSSL or GnuTLS defaults, DEFAULT
and NORMAL respectively.
- When adding GLINE's or KLINE's to ngIRCd 21 (or newer), all clients matching
the new mask will be KILL'ed. This was not the case with earlier versions
that only added the mask but didn't kill already connected users.
Differences to version 19.x Differences to version 19.x
- Starting with ngIRCd 20, users can "cloak" their hostname only when the - Starting with ngIRCd 20, users can "cloak" their hostname only when the
configuration variable "CloakHostModeX" (introduced in 19.2) is set. configuration variable "CloakHostModeX" (introduced in 19.2) is set.
Otherwise, only IRC operators, other servers, and services are allowed to Otherwise, only IRC opertators, other servers, and services are allowed to
set mode +x. This prevents regular users from changing their hostmask to set mode +x. This prevents regular users from changing their hostmask to
the name of the IRC server itself, which confused quite a few people ;-) the name of the IRC server itself, which confused quite a few people ;-)

View File

@@ -1,6 +1,6 @@
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -15,8 +15,9 @@ SUBDIRS = doc src man contrib
EXTRA_DIST = autogen.sh configure.ng .mailmap EXTRA_DIST = autogen.sh configure.ng .mailmap
clean-local: osxpkg-clean clean-local:
rm -f build-stamp* rm -f build-stamp*
rm -rf ngircd.dest
maintainer-clean-local: maintainer-clean-local:
rm -rf autom4te.cache rm -rf autom4te.cache
@@ -61,18 +62,14 @@ deb:
dpkg-buildpackage -rfakeroot -i dpkg-buildpackage -rfakeroot -i
osxpkg: have-packagemaker osxpkg-dest osxpkg: have-packagemaker osxpkg-dest
cd contrib/MacOSX && packagemaker --no-recommend \ cd contrib/MacOSX && packagemaker \
--doc ngIRCd.pmdoc \ --doc ngIRCd.pmdoc \
--out ../../$(distdir).mpkg --out ../../$(distdir).mpkg
rm -f $(distdir).mpkg.zip rm -f $(distdir).mpkg.zip
zip -ro9 $(distdir).mpkg.zip $(distdir).mpkg zip -ro9 $(distdir).mpkg.zip $(distdir).mpkg
make osxpkg-clean
osxpkg-clean:
[ ! -e ngircd.dest ] || sudo -n rm -rf ngircd.dest
rm -rf ngircd.dest $(distdir).mpkg rm -rf ngircd.dest $(distdir).mpkg
osxpkg-dest: have-xcodebuild osxpkg-clean clean osxpkg-dest: have-xcodebuild clean
./configure --prefix=/opt/ngircd ./configure --prefix=/opt/ngircd
make xcode make xcode
make -C contrib/MacOSX de.barton.ngircd.plist make -C contrib/MacOSX de.barton.ngircd.plist
@@ -85,9 +82,8 @@ osxpkg-dest: have-xcodebuild osxpkg-clean clean
rm ngircd.dest/opt/ngircd/etc/ngircd.conf rm ngircd.dest/opt/ngircd/etc/ngircd.conf
echo "Have a nice day IRCing!" >ngircd.dest/opt/ngircd/etc/ngircd.motd echo "Have a nice day IRCing!" >ngircd.dest/opt/ngircd/etc/ngircd.motd
chmod -R a-s,og-w,a+rX ngircd.dest chmod -R a-s,og-w,a+rX ngircd.dest
sudo chown -R root:wheel ngircd.dest
.PHONY: deb have-packagemaker have-xcodebuild lint osxpkg osxpkg-clean \ .PHONY: deb have-packagemaker have-xcodebuild lint osxpkg osxpkg-dest rpm \
osxpkg-dest rpm srcdoc testsuite xcode xcode-clean srcdoc testsuite xcode xcode-clean
# -eof- # -eof-

92
NEWS
View File

@@ -9,99 +9,11 @@
-- NEWS -- -- NEWS --
ngIRCd 21~rc2 (2013-10-20)
- Report the correct configuration file name on configuration errors,
support longer configuration lines, and warn when lines are truncated.
ngIRCd 21~rc1 (2013-10-05)
- Actually KILL clients on GLINE/KLINE. (Closes bug #156)
- Add support to show all user links using the "STATS L" (uppercase)
command (restricted to IRC Operators).
- Implement configurable SSL cipher list selection for GnuTLS and OpenSSL
using the new configuration option "CipherList". In addition, this
changes the defaults to more secure values: "HIGH:!aNULL:@STRENGTH" for
OpenSSL, and "SECURE128" for GnuTLS.
- Show connection flag "s" (SSL) in RPL_TRACE{LINK|SERVER} messages: now
you can check if a server-to-server link is SSL-encrypted or not using
the IRC "TRACE" command.
- Implement the new configuration option "DefaultUserModes" which lists
user modes that become automatically set on new local clients right
after login. Please note that only modes can be set that the client
could set on itself, so you can't set "a" (away) or "o" (IRC Op),
for example! User modes "i" (invisible) or "x" (cloaked) etc. are
"interesting", though. (Closes bug #160)
- Add support for the new METADATA "account" property, which allows
services to automatically identify users after netsplits and across
service restarts.
- Implement a new configuration option "AllowedChannelTypes" that lists
all allowed channel types (channel prefixes) for newly created channels
on the local server. By default, all supported channel types are allowed.
If set to the empty string, local clients can't create new channels at
all, which equals the old "PredefChannelsOnly = yes" setting.
This change deprecates the "PredefChannelsOnly" variable, too, but it is
still supported and translated to the appropriate "AllowedChannelTypes"
setting. When the old "PredefChannelsOnly" variable is processed, a
warning message is logged. (Closes bug #152)
- Add support for "client certificate fingerprinting". When a client
passes an SSL certificate to the server, the "fingerprint" will be
forwarded in the network which enables IRC services to identify the
user using this certificate and not using passwords.
- Implement a new configuration option "IncludeDir" in the "[Options]"
section that can be used to specify a directory which can contain
further configuration files and configuration file snippets matching
the pattern "*.conf". These files are read in after the main server
configuration file ("ngircd.conf" by default) has been read in and
parsed. The default is "$SYSCONFDIR/ngircd.conf.d", so that it is
possible to adjust the configuration only by placing additional files
into this directory. (Closes bug #157)
- Add Travis-CI configuration file (".travis.yml") to project.
- ngIRCd now accepts user names including "@" characters, saves the
unmodified name for authentication but stores only the part in front
of the "@" character as "IRC user name". And the latter is how
ircd2.11, Bahamut, and irc-seven behave as well. (Closes bug #155)
- Lots of IRC "information functions" like ADMIN, INFO, ... now accept
server masks and names of connected users (in addition to server names)
for specifying the target server of the command. (Closes bug #153)
- Implement a new configuration option "IdleTimeout" in the "[Limits]"
section of the configuration file which can be used to set a timeout
in seconds after which the whole daemon will shutdown when no more
connections are left active after handling at least one client.
The default is 0, "never".
This can be useful for testing or when ngIRCd is started using "socket
activation" with systemd(8), for example.
- Implement support for systemd(8) "socket activation".
- Enable WHOIS to display information about IRC Services using the new
numeric 310(RPL_WHOISSERVICE) This numeric is used for this purpose by
InspIRCd, for example -- but as usual, other numerics are in use, too,
like 613 in UltimateIRCd ...
Please note that neither the Operator (+o) not the "bot status" (+B)
of an IRC service is displayed in the output.
- Update systemd(8) example configuration files in ./contrib/ directory:
the "ngircd.service" file now uses the "forking" service type which
enhances the log messages shown by "systemctl status ngircd.service",
and the new "ngircd.socket" file configures a systemd socket that
configures a socket for ngIRCd and launches the daemon on demand.
- Enhance help system and the HELP command: now a "help text file" can be
set using the new configuration option "HelpFile" ("global" section),
which is read in and parsed on server startup and configuration reload,
and then is used to output individual help texts to specific topics.
Please see the file ./doc/Commands.txt for details.
ngIRCd 20.3 (2013-08-23)
- This release is a bugfix release only, without new features.
- Security: Fix a denial of service bug (server crash) which could happen
when the configuration option "NoticeAuth" is enabled (which is NOT the
default) and ngIRCd failed to send the "notice auth" messages to new
clients connecting to the server (CVE-2013-5580).
ngIRCd 20.2 (2013-02-15) ngIRCd 20.2 (2013-02-15)
- This release is a bugfix release only, without new features. - This release is a bugfix release only, without new features.
- Security: Fix a denial of service bug in the function handling KICK - Security: Fix a denial of service bug in the function handling KICK
commands that could be used by arbitrary users to to crash the daemon commands that could be used by arbitrary users to to crash the daemon.
(CVE-2013-1747).
ngIRCd 20.1 (2013-01-02) ngIRCd 20.1 (2013-01-02)
@@ -111,7 +23,7 @@ ngIRCd 20 (2012-12-17)
- Allow user names ("INDENT") up to 20 characters when ngIRCd has not - Allow user names ("INDENT") up to 20 characters when ngIRCd has not
been configured for "strict RFC mode". This is useful if you are using been configured for "strict RFC mode". This is useful if you are using
external (PAM) authentication mechanisms that require longer user names. external (PAM) authenticaion mechanisms that require longer user names.
Patch suggested by Brett Smith <brett@w3.org>, see Patch suggested by Brett Smith <brett@w3.org>, see
<http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>. <http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>.

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -73,12 +73,8 @@ Search()
for name in $searchlist; do for name in $searchlist; do
$EXIST "${name}" >/dev/null 2>&1 $EXIST "${name}" >/dev/null 2>&1
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
"${name}" --version 2>&1 \ echo "${name}"
| grep -v "environment variable" >/dev/null 2>&1 return 0
if [ $? -eq 0 ]; then
echo "${name}"
return 0
fi
fi fi
done done
@@ -148,15 +144,6 @@ echo "Searching for required tools ..."
[ -z "$AUTOCONF" ] && AUTOCONF=`Search autoconf 2` [ -z "$AUTOCONF" ] && AUTOCONF=`Search autoconf 2`
[ "$VERBOSE" = "1" ] && echo " - AUTOCONF=$AUTOCONF" [ "$VERBOSE" = "1" ] && echo " - AUTOCONF=$AUTOCONF"
AUTOCONF_VERSION=`echo $AUTOCONF | cut -d'-' -f2-`
[ -n "$AUTOCONF_VERSION" -a "$AUTOCONF_VERSION" != "autoconf" ] \
&& export AUTOCONF_VERSION || unset AUTOCONF_VERSION
[ "$VERBOSE" = "1" ] && echo " - AUTOCONF_VERSION=$AUTOCONF_VERSION"
AUTOMAKE_VERSION=`echo $AUTOMAKE | cut -d'-' -f2-`
[ -n "$AUTOMAKE_VERSION" -a "$AUTOMAKE_VERSION" != "automake" ] \
&& export AUTOMAKE_VERSION || unset AUTOMAKE_VERSION
[ "$VERBOSE" = "1" ] && echo " - AUTOMAKE_VERSION=$AUTOMAKE_VERSION"
[ $# -gt 0 ] && CONFIGURE_ARGS=" $@" || CONFIGURE_ARGS="" [ $# -gt 0 ] && CONFIGURE_ARGS=" $@" || CONFIGURE_ARGS=""
[ -z "$GO" -a -n "$CONFIGURE_ARGS" ] && GO=1 [ -z "$GO" -a -n "$CONFIGURE_ARGS" ] && GO=1
@@ -169,23 +156,21 @@ AUTOMAKE_VERSION=`echo $AUTOMAKE | cut -d'-' -f2-`
AM_VERSION=`$AUTOMAKE --version | head -n 1 | sed -e 's/.* //g'` AM_VERSION=`$AUTOMAKE --version | head -n 1 | sed -e 's/.* //g'`
ifs=$IFS; IFS="."; set $AM_VERSION; IFS=$ifs ifs=$IFS; IFS="."; set $AM_VERSION; IFS=$ifs
AM_MAJOR="$1"; AM_MINOR="$2"; AM_PATCHLEVEL="$3" AM_MAJOR="$1"; AM_MINOR="$2"; AM_PATCHLEVEL="$3"
echo "Detected automake $AM_VERSION ..."
AM_MAKEFILES="src/ipaddr/Makefile.ng src/ngircd/Makefile.ng src/testsuite/Makefile.ng src/tool/Makefile.ng" AM_MAKEFILES="src/ipaddr/Makefile.ng src/ngircd/Makefile.ng src/testsuite/Makefile.ng src/tool/Makefile.ng"
# De-ANSI-fication?
if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -lt "12" ]; then if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -lt "12" ]; then
# automake < 1.12 => automatic de-ANSI-fication support available # automake < 1.12 => automatic de-ANSI-fication support available
echo " - Enabling de-ANSI-fication support." echo "Enabling de-ANSI-fication support (automake $AM_VERSION) ..."
sed -e "s|^__ng_PROTOTYPES__|AM_C_PROTOTYPES|g" configure.ng >configure.ac sed -e "s|^__ng_PROTOTYPES__|AM_C_PROTOTYPES|g" configure.ng >configure.ac
DEANSI_START="" DEANSI_START=""
DEANSI_END="" DEANSI_END=""
else else
# automake >= 1.12 => no de-ANSI-fication support available # automake >= 1.12 => no de-ANSI-fication support available
echo " - Disabling de-ANSI-fication support." echo "Disabling de-ANSI-fication support (automake $AM_VERSION) ..."
sed -e "s|^__ng_PROTOTYPES__|AC_C_PROTOTYPES|g" configure.ng >configure.ac sed -e "s|^__ng_PROTOTYPES__|AC_C_PROTOTYPES|g" configure.ng >configure.ac
DEANSI_START="#" DEANSI_START="#"
DEANSI_END=" (disabled by ./autogen.sh script)" DEANSI_END=" # disabled by ./autogen.sh script"
fi fi
# Serial test harness? # Serial test harness?
if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -ge "13" ]; then if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -ge "13" ]; then
@@ -208,7 +193,7 @@ done
export ACLOCAL AUTOHEADER AUTOMAKE AUTOCONF export ACLOCAL AUTOHEADER AUTOMAKE AUTOCONF
# Generate files # Generate files
echo "Generating files using \"$AUTOCONF\" and \"$AUTOMAKE\" ..." echo "Generating files using GNU $AUTOCONF and $AUTOMAKE ..."
Run $ACLOCAL && \ Run $ACLOCAL && \
Run $AUTOCONF && \ Run $AUTOCONF && \
Run $AUTOHEADER && \ Run $AUTOHEADER && \

View File

@@ -1,6 +1,6 @@
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -110,7 +110,7 @@ esac
# Add additional CFLAGS, eventually specified on the command line: # Add additional CFLAGS, eventually specified on the command line:
test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD" test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD"
CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"' -DDOCDIR='\"\$(docdir)\"'" CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'"
# -- Headers -- # -- Headers --
@@ -187,9 +187,8 @@ AC_CHECK_FUNCS([ \
# Optional functions # Optional functions
AC_CHECK_FUNCS_ONCE([ \ AC_CHECK_FUNCS_ONCE([ \
arc4random gai_strerror getaddrinfo getnameinfo inet_aton sigaction \ gai_strerror getaddrinfo getnameinfo inet_aton sigaction sigprocmask \
sigprocmask snprintf vsnprintf strdup strndup strlcpy strlcat strtok_r \ snprintf vsnprintf strdup strlcpy strlcat strtok_r waitpid])
waitpid])
# -- Configuration options -- # -- Configuration options --
@@ -519,8 +518,7 @@ if test "$x_ircplus_on" = "yes"; then
# CHARCONV is the only function depending on it. # CHARCONV is the only function depending on it.
x_iconv_on=no x_iconv_on=no
AC_ARG_WITH(iconv, AC_ARG_WITH(iconv,
AS_HELP_STRING([--with-iconv], [ --with-iconv enable character conversation using libiconv],
[enable character conversion using libiconv]),
[ if test "$withval" != "no"; then [ if test "$withval" != "no"; then
if test "$withval" != "yes"; then if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS" CFLAGS="-I$withval/include $CFLAGS"
@@ -528,15 +526,11 @@ if test "$x_ircplus_on" = "yes"; then
LDFLAGS="-L$withval/lib $LDFLAGS" LDFLAGS="-L$withval/lib $LDFLAGS"
fi fi
AC_CHECK_LIB(iconv, iconv_open) AC_CHECK_LIB(iconv, iconv_open)
AC_CHECK_FUNCS(iconv_open, x_iconv_on=yes) AC_CHECK_FUNCS(iconv_open, x_iconv_on=yes,
if test "$x_iconv_on" != "yes"; then
AC_CHECK_LIB(iconv, libiconv_open)
AC_CHECK_FUNCS(libiconv_open, x_iconv_on=yes)
fi
if test "$x_iconv_on" != "yes"; then
AC_MSG_ERROR([Can't enable libiconv support!]) AC_MSG_ERROR([Can't enable libiconv support!])
fi )
fi ] fi
]
) )
if test "$x_iconv_on" = "yes"; then if test "$x_iconv_on" = "yes"; then
AC_DEFINE(ICONV, 1) AC_DEFINE(ICONV, 1)
@@ -703,7 +697,7 @@ test "$x_ipv6_on" = "yes" \
&& echo $ECHO_N "yes $ECHO_C" \ && echo $ECHO_N "yes $ECHO_C" \
|| echo $ECHO_N "no $ECHO_C" || echo $ECHO_N "no $ECHO_C"
echo $ECHO_N " I/O backend: $ECHO_C" echo $ECHO_N " I/O backend: $ECHO_C"
echo "$x_io_backend" echo "\"$x_io_backend\""
echo $ECHO_N " PAM support: $ECHO_C" echo $ECHO_N " PAM support: $ECHO_C"
test "$x_pam_on" = "yes" \ test "$x_pam_on" = "yes" \

View File

@@ -1,21 +1,3 @@
ngircd (21~rc2-0ab1) unstable; urgency=low
* New "upstream" release candidate 2 for ngIRCd Release 21.
-- Alexander Barton <alex@barton.de> Sun, 20 Oct 2013 15:50:03 +0200
ngircd (21~rc1-0ab1) unstable; urgency=low
* New "upstream" release candidate 1 for ngIRCd Release 21.
-- Alexander Barton <alex@barton.de> Sat, 05 Oct 2013 23:24:09 +0200
ngircd (20.3-0ab1) unstable; urgency=high
* New "upstream" release, fixing a security related bug: ngIRCd 20.3.
-- Alexander Barton <alex@barton.de> Fri, 23 Aug 2013 21:53:21 +0200
ngircd (20.2-0ab1) unstable; urgency=high ngircd (20.2-0ab1) unstable; urgency=high
* New "upstream" release, fixing a security related bug: ngIRCd 20.2. * New "upstream" release, fixing a security related bug: ngIRCd 20.2.

View File

@@ -1,6 +1,8 @@
# #
# Defaults for ngIRCd start and stop script # Defaults for ngIRCd start and stop script
# #
# $Id: ngircd.default,v 1.1 2003/12/31 17:20:11 alex Exp $
#
# Parameters to pass to the ngircd daemon on startup, see ngircd(8) for # Parameters to pass to the ngircd daemon on startup, see ngircd(8) for
# possible options (default: empty). # possible options (default: empty).

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# ngIRCd start and stop script for Debian-based systems # ngIRCd start and stop script for Debian-based systems
# Copyright 2008-2013 Alexander Barton <alex@barton.de> # Copyright 2008-2010 Alexander Barton <alex@barton.de>
# #
### BEGIN INIT INFO ### BEGIN INIT INFO
@@ -24,13 +24,13 @@ PARAMS=""
STARTTIME=1 STARTTIME=1
DIETIME=10 DIETIME=10
test -x $DAEMON || exit 5
test -h "$0" && me=`readlink $0` || me="$0" test -h "$0" && me=`readlink $0` || me="$0"
BASENAME=`basename $me` BASENAME=`basename $me`
test -r /etc/default/$BASENAME && . /etc/default/$BASENAME test -r /etc/default/$BASENAME && . /etc/default/$BASENAME
test -x $DAEMON || exit 5
# LSB compatibility functions that become used if there is no local # LSB compatibility functions that become used if there is no local
# include file available. # include file available.
log_daemon_msg() { log_daemon_msg() {

View File

@@ -216,7 +216,7 @@ binary-arch: build install
dh_installdocs -a dh_installdocs -a
dh_installinit -a dh_installinit -a
dh_strip -a --no-package=ngircd-full-dbg dh_strip -a --no-package=ngircd-full-dbg
dh_compress -a -XCommands.txt dh_compress -a
dh_fixperms -a dh_fixperms -a
dh_installdeb -a dh_installdeb -a
dh_shlibdeps -a dh_shlibdeps -a

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -12,21 +12,16 @@
*/ */
#define PACKAGE_NAME "ngIRCd" #define PACKAGE_NAME "ngIRCd"
# define PACKAGE "ngircd" #define PACKAGE "ngircd"
#ifndef VERSION #ifndef VERSION
# define VERSION "??("__DATE__")" #define VERSION "??("__DATE__")"
#endif #endif
#ifndef HOST_VENDOR
# define HOST_VENDOR "apple"
# define HOST_OS "darwin"
# ifdef __x86_64
# define HOST_CPU "x86_64"
# endif
#endif
#define SYSCONFDIR "/etc/ngircd" #define SYSCONFDIR "/etc/ngircd"
#define DOCDIR "/usr/share/doc/ngircd"
#ifndef TARGET_VENDOR
#define TARGET_VENDOR "apple"
#define TARGET_OS "darwin"
#endif
/* -- Build options -- */ /* -- Build options -- */

View File

@@ -1 +1 @@
<pkg-contents spec="1.12"><f n="ngircd.dest" o="root" g="admin" p="16877" pt="../../ngircd.dest" m="false" t="file"><f n="opt" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="16877"><f n="etc" o="root" g="admin" p="16877"><f n="ngircd.motd" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="sbin" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="33261"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="share" o="root" g="admin" p="16877"><f n="doc" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="16877"><f n="AUTHORS" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Bopm.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="ChangeLog" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="COPYING" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="FAQ.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="GIT.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="HowToRelease.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="INSTALL" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="NEWS" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="PAM.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Platforms.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Protocol.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-AUX.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-BeOS.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-Interix.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="RFC.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="sample-ngircd.conf" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Services.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="SSL.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="man" o="root" g="admin" p="16877"><f n="man5" o="root" g="admin" p="16877"><f n="ngircd.conf.5" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="man8" o="root" g="admin" p="16877"><f n="ngircd.8" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f></pkg-contents> <pkg-contents spec="1.12"><f n="ngircd.dest" o="root" g="admin" p="16877" pt="/Users/alex/Develop/ngircd/alex.git/ngircd.dest" m="false" t="file"><f n="opt" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="16877"><f n="etc" o="root" g="admin" p="16877"><f n="ngircd.motd" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="sbin" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="33261"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="share" o="root" g="admin" p="16877"><f n="doc" o="root" g="admin" p="16877"><f n="ngircd" o="root" g="admin" p="16877"><f n="AUTHORS" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Bopm.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="ChangeLog" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="COPYING" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="FAQ.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="GIT.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="HowToRelease.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="INSTALL" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="NEWS" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="PAM.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Platforms.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Protocol.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-AUX.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-BeOS.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="README-Interix.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="RFC.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="sample-ngircd.conf" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="Services.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><f n="SSL.txt" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="man" o="root" g="admin" p="16877"><f n="man5" o="root" g="admin" p="16877"><f n="ngircd.conf.5" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><f n="man8" o="root" g="admin" p="16877"><f n="ngircd.8" o="root" g="admin" p="33188"><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f><mod>group</mod><mod>owner</mod></f></pkg-contents>

View File

@@ -1 +1 @@
<pkgref spec="1.12" uuid="46208410-4A1B-48C6-97BD-DE284F13F864"><config><identifier>de.barton.ngircd.daemon.pkg</identifier><version>17.1</version><description></description><post-install type="none"/><requireAuthorization/><installFrom>../../ngircd.dest</installFrom><installTo mod="true">/</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>extraFiles</mod><mod>installTo</mod><mod>installTo.isAbsoluteType</mod><mod>scripts.preinstall.path</mod><mod>identifier</mod><mod>parent</mod><mod>version</mod><mod>installTo.path</mod><mod>scripts.preupgrade.path</mod><mod>requireAuthorization</mod></config><contents><file-list>02ngircd-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents><extra-files/></pkgref> <pkgref spec="1.12" uuid="46208410-4A1B-48C6-97BD-DE284F13F864"><config><identifier>de.barton.ngircd.daemon.pkg</identifier><version>17.1</version><description></description><post-install type="none"/><requireAuthorization/><installFrom>/Users/alex/Develop/ngircd/alex.git/ngircd.dest</installFrom><installTo mod="true">/</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>extraFiles</mod><mod>installTo</mod><mod>installTo.isAbsoluteType</mod><mod>scripts.preinstall.path</mod><mod>identifier</mod><mod>parent</mod><mod>version</mod><mod>installTo.path</mod><mod>scripts.preupgrade.path</mod><mod>requireAuthorization</mod></config><contents><file-list>02ngircd-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents><extra-files/></pkgref>

View File

@@ -1,5 +1,5 @@
<pkmkdoc spec="1.12"><properties><title>ngIRCd</title><build>../../ngIRCd.mpkg</build><organization>de.barton.ngircd</organization><userSees ui="both"/><min-target os="2"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>ngIRCd next generation Internet Relay Chat (IRC) server <pkmkdoc spec="1.12"><properties><title>ngIRCd</title><build>/Users/alex/Desktop/ngIRCd.mpkg</build><organization>de.barton.ngircd</organization><userSees ui="both"/><min-target os="2"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>ngIRCd next generation Internet Relay Chat (IRC) server
daemon</description><contents><choice title="ngIRCd daemon" id="choicengircd" tooltip="ngIRCd daemon, documentation and manual pages" description="Binaries, documentation and manual pages of the ngIRCd, the next generation IRC (Internet Relay Chat) daemon. This package will be installed into /opt/ngircd." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="de.barton.ngircd.daemon.pkg"/></choice><choice title="Start and stop script" id="choicelaunchscript" tooltip="LaunchDaemon start and stop script" description="Installs the ngIRCd start and stop script for the &quot;launch daemon&quot;. If this is an update/upgrade, and ngIRCd is already running, it will be automatically restarted." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="de.barton.ngircd.launchscript.pkg"/></choice></contents><resources bg-scale="none" bg-align="bottomleft"><locale lang="en"><resource type="background">../ngIRCd-Logo.gif</resource><resource mime-type="text/rtf" kind="embedded" type="license"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 daemon</description><contents><choice title="ngIRCd daemon" id="choicengircd" tooltip="ngIRCd daemon, documentation and manual pages" description="Binaries, documentation and manual pages of the ngIRCd, the next generation IRC (Internet Relay Chat) daemon. This package will be installed into /opt/ngircd." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="de.barton.ngircd.daemon.pkg"/></choice><choice title="Start and stop script" id="choicelaunchscript" tooltip="LaunchDaemon start and stop script" description="Installs the ngIRCd start and stop script for the &quot;launch daemon&quot;. If this is an update/upgrade, and ngIRCd is already running, it will be automatically restarted." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="de.barton.ngircd.launchscript.pkg"/></choice></contents><resources bg-scale="none" bg-align="bottomleft"><locale lang="en"><resource type="background">/Users/alex/Develop/ngircd/alex.git/contrib/ngIRCd-Logo.gif</resource><resource mime-type="text/rtf" kind="embedded" type="license"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;} {\colortbl;\red255\green255\blue255;}
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural

View File

@@ -64,27 +64,12 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
FA18A63E16CEDDCE00132F66 /* configure.ng */ = {isa = PBXFileReference; lastKnownFileType = text; name = configure.ng; path = ../../configure.ng; sourceTree = "<group>"; }; FA1A6BBC0D6857BB00AA8F71 /* misc-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "misc-test.e"; sourceTree = "<group>"; };
FA18A63F16CEDE2300132F66 /* ngircd.service */ = {isa = PBXFileReference; lastKnownFileType = text; path = ngircd.service; sourceTree = "<group>"; };
FA18A64016CEDE2300132F66 /* ngircd.socket */ = {isa = PBXFileReference; lastKnownFileType = text; path = ngircd.socket; sourceTree = "<group>"; };
FA18A64116CEDE3500132F66 /* ngircd.pam */ = {isa = PBXFileReference; lastKnownFileType = text; path = ngircd.pam; sourceTree = "<group>"; };
FA18A64216CEDE5700132F66 /* de.barton.ngircd.plist.tmpl */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = de.barton.ngircd.plist.tmpl; sourceTree = "<group>"; };
FA18A64316CEDE8100132F66 /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA18A64416CEDFCE00132F66 /* Commands.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Commands.txt; sourceTree = "<group>"; };
FA18A64516CEE0C700132F66 /* Makefile.ng */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.ng; path = ipaddr/Makefile.ng; sourceTree = "<group>"; };
FA18A64616CEE0DD00132F66 /* Makefile.ng */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.ng; sourceTree = "<group>"; };
FA18A64716CEE14900132F66 /* Makefile.ng */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.ng; sourceTree = "<group>"; };
FA18A64A16CEE18100132F66 /* Makefile.ng */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.ng; sourceTree = "<group>"; };
FA18A64C16CEE1AC00132F66 /* mode-test.e */ = {isa = PBXFileReference; lastKnownFileType = text; path = "mode-test.e"; sourceTree = "<group>"; };
FA18A64D16CEE1D900132F66 /* whois-test.e */ = {isa = PBXFileReference; lastKnownFileType = text; path = "whois-test.e"; sourceTree = "<group>"; };
FA18A64E16CEE24B00132F66 /* misc-test.e */ = {isa = PBXFileReference; lastKnownFileType = text; path = "misc-test.e"; sourceTree = "<group>"; };
FA18A64F16CEE27700132F66 /* Makefile.ng */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.ng; sourceTree = "<group>"; };
FA1A6BBD0D6857D900AA8F71 /* who-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "who-test.e"; sourceTree = "<group>"; }; FA1A6BBD0D6857D900AA8F71 /* who-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "who-test.e"; sourceTree = "<group>"; };
FA1DBB6716C707D200D4F838 /* irc-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-macros.h"; sourceTree = "<group>"; };
FA2D564811EA158B00D37A35 /* pam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pam.h; sourceTree = "<group>"; }; FA2D564811EA158B00D37A35 /* pam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pam.h; sourceTree = "<group>"; };
FA2D564911EA158B00D37A35 /* pam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pam.c; sourceTree = "<group>"; }; FA2D564911EA158B00D37A35 /* pam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pam.c; sourceTree = "<group>"; };
FA2D567A11EA1AB300D37A35 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = usr/lib/libpam.dylib; sourceTree = SDKROOT; }; FA2D567A11EA1AB300D37A35 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = usr/lib/libpam.dylib; sourceTree = SDKROOT; };
FA322BBA0CEF72E4001761B3 /* ngIRCd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = ngIRCd; path = ngircd; sourceTree = BUILT_PRODUCTS_DIR; }; FA322BBA0CEF72E4001761B3 /* ngIRCd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ngIRCd; sourceTree = BUILT_PRODUCTS_DIR; };
FA322CD60CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; }; FA322CD60CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322CD90CEF74B1001761B3 /* array.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = array.c; sourceTree = "<group>"; }; FA322CD90CEF74B1001761B3 /* array.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = array.c; sourceTree = "<group>"; };
FA322CDA0CEF74B1001761B3 /* array.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = "<group>"; }; FA322CDA0CEF74B1001761B3 /* array.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = "<group>"; };
@@ -127,6 +112,7 @@
FA322CFF0CEF74B1001761B3 /* lists.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = lists.h; sourceTree = "<group>"; }; FA322CFF0CEF74B1001761B3 /* lists.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = lists.h; sourceTree = "<group>"; };
FA322D000CEF74B1001761B3 /* log.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = "<group>"; }; FA322D000CEF74B1001761B3 /* log.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = "<group>"; };
FA322D010CEF74B1001761B3 /* log.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; }; FA322D010CEF74B1001761B3 /* log.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
FA322D020CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D030CEF74B1001761B3 /* match.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = match.c; sourceTree = "<group>"; }; FA322D030CEF74B1001761B3 /* match.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = match.c; sourceTree = "<group>"; };
FA322D040CEF74B1001761B3 /* match.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = match.h; sourceTree = "<group>"; }; FA322D040CEF74B1001761B3 /* match.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = match.h; sourceTree = "<group>"; };
FA322D050CEF74B1001761B3 /* messages.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = messages.h; sourceTree = "<group>"; }; FA322D050CEF74B1001761B3 /* messages.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = messages.h; sourceTree = "<group>"; };
@@ -140,6 +126,7 @@
FA322D110CEF74B1001761B3 /* ansi2knr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = ansi2knr.c; sourceTree = "<group>"; }; FA322D110CEF74B1001761B3 /* ansi2knr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = ansi2knr.c; sourceTree = "<group>"; };
FA322D120CEF74B1001761B3 /* exp.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = exp.h; sourceTree = "<group>"; }; FA322D120CEF74B1001761B3 /* exp.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = exp.h; sourceTree = "<group>"; };
FA322D130CEF74B1001761B3 /* imp.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = imp.h; sourceTree = "<group>"; }; FA322D130CEF74B1001761B3 /* imp.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = imp.h; sourceTree = "<group>"; };
FA322D140CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D150CEF74B1001761B3 /* portab.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = portab.h; sourceTree = "<group>"; }; FA322D150CEF74B1001761B3 /* portab.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = portab.h; sourceTree = "<group>"; };
FA322D160CEF74B1001761B3 /* portabtest.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = portabtest.c; sourceTree = "<group>"; }; FA322D160CEF74B1001761B3 /* portabtest.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = portabtest.c; sourceTree = "<group>"; };
FA322D170CEF74B1001761B3 /* splint.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = splint.h; sourceTree = "<group>"; }; FA322D170CEF74B1001761B3 /* splint.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = splint.h; sourceTree = "<group>"; };
@@ -151,6 +138,8 @@
FA322D1F0CEF74B1001761B3 /* connect-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "connect-test.e"; sourceTree = "<group>"; }; FA322D1F0CEF74B1001761B3 /* connect-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "connect-test.e"; sourceTree = "<group>"; };
FA322D200CEF74B1001761B3 /* functions.inc */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; path = functions.inc; sourceTree = "<group>"; }; FA322D200CEF74B1001761B3 /* functions.inc */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; path = functions.inc; sourceTree = "<group>"; };
FA322D210CEF74B1001761B3 /* getpid.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = getpid.sh; sourceTree = "<group>"; }; FA322D210CEF74B1001761B3 /* getpid.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = getpid.sh; sourceTree = "<group>"; };
FA322D220CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D230CEF74B1001761B3 /* mode-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "mode-test.e"; sourceTree = "<group>"; };
FA322D250CEF74B1001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; }; FA322D250CEF74B1001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
FA322D260CEF74B1001761B3 /* start-server.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "start-server.sh"; sourceTree = "<group>"; }; FA322D260CEF74B1001761B3 /* start-server.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "start-server.sh"; sourceTree = "<group>"; };
FA322D270CEF74B1001761B3 /* stop-server.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "stop-server.sh"; sourceTree = "<group>"; }; FA322D270CEF74B1001761B3 /* stop-server.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "stop-server.sh"; sourceTree = "<group>"; };
@@ -160,6 +149,9 @@
FA322D2B0CEF74B1001761B3 /* test-loop.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "test-loop.sh"; sourceTree = "<group>"; }; FA322D2B0CEF74B1001761B3 /* test-loop.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "test-loop.sh"; sourceTree = "<group>"; };
FA322D2C0CEF74B1001761B3 /* tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = tests.sh; sourceTree = "<group>"; }; FA322D2C0CEF74B1001761B3 /* tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = tests.sh; sourceTree = "<group>"; };
FA322D2D0CEF74B1001761B3 /* wait-tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "wait-tests.sh"; sourceTree = "<group>"; }; FA322D2D0CEF74B1001761B3 /* wait-tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "wait-tests.sh"; sourceTree = "<group>"; };
FA322D300CEF74B1001761B3 /* ansi2knr.1 */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.man; path = ansi2knr.1; sourceTree = "<group>"; };
FA322D310CEF74B1001761B3 /* ansi2knr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = ansi2knr.c; sourceTree = "<group>"; };
FA322D320CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D330CEF74B1001761B3 /* tool.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = tool.c; sourceTree = "<group>"; }; FA322D330CEF74B1001761B3 /* tool.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = tool.c; sourceTree = "<group>"; };
FA322D340CEF74B1001761B3 /* tool.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = tool.h; sourceTree = "<group>"; }; FA322D340CEF74B1001761B3 /* tool.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = tool.h; sourceTree = "<group>"; };
FA322D5A0CEF750F001761B3 /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = AUTHORS; path = ../../AUTHORS; sourceTree = SOURCE_ROOT; }; FA322D5A0CEF750F001761B3 /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = AUTHORS; path = ../../AUTHORS; sourceTree = SOURCE_ROOT; };
@@ -167,6 +159,7 @@
FA322D5C0CEF750F001761B3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = ChangeLog; path = ../../ChangeLog; sourceTree = SOURCE_ROOT; }; FA322D5C0CEF750F001761B3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = ChangeLog; path = ../../ChangeLog; sourceTree = SOURCE_ROOT; };
FA322D5E0CEF750F001761B3 /* config.guess */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; name = config.guess; path = ../../config.guess; sourceTree = SOURCE_ROOT; }; FA322D5E0CEF750F001761B3 /* config.guess */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; name = config.guess; path = ../../config.guess; sourceTree = SOURCE_ROOT; };
FA322D5F0CEF750F001761B3 /* config.sub */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; name = config.sub; path = ../../config.sub; sourceTree = SOURCE_ROOT; }; FA322D5F0CEF750F001761B3 /* config.sub */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; name = config.sub; path = ../../config.sub; sourceTree = SOURCE_ROOT; };
FA322D600CEF750F001761B3 /* configure.in */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = configure.in; path = ../../configure.in; sourceTree = SOURCE_ROOT; };
FA322D610CEF750F001761B3 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = COPYING; path = ../../COPYING; sourceTree = SOURCE_ROOT; }; FA322D610CEF750F001761B3 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = COPYING; path = ../../COPYING; sourceTree = SOURCE_ROOT; };
FA322D620CEF750F001761B3 /* INSTALL */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = INSTALL; path = ../../INSTALL; sourceTree = SOURCE_ROOT; }; FA322D620CEF750F001761B3 /* INSTALL */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = INSTALL; path = ../../INSTALL; sourceTree = SOURCE_ROOT; };
FA322D630CEF750F001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = ../../Makefile.am; sourceTree = SOURCE_ROOT; }; FA322D630CEF750F001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = ../../Makefile.am; sourceTree = SOURCE_ROOT; };
@@ -181,8 +174,9 @@
FA322D700CEF7523001761B3 /* ngircd.init */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.init; sourceTree = "<group>"; }; FA322D700CEF7523001761B3 /* ngircd.init */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.init; sourceTree = "<group>"; };
FA322D710CEF7523001761B3 /* ngircd.postinst */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.postinst; sourceTree = "<group>"; }; FA322D710CEF7523001761B3 /* ngircd.postinst */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.postinst; sourceTree = "<group>"; };
FA322D720CEF7523001761B3 /* rules */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = rules; sourceTree = "<group>"; }; FA322D720CEF7523001761B3 /* rules */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = rules; sourceTree = "<group>"; };
FA322D8D0CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = MacOSX/Makefile.am; sourceTree = "<group>"; }; FA322D8D0CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = ngIRCd.xcodeproj; sourceTree = "<group>"; }; FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = ngIRCd.xcodeproj; sourceTree = "<group>"; };
FA322D910CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D920CEF7523001761B3 /* ngindent */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngindent; sourceTree = "<group>"; }; FA322D920CEF7523001761B3 /* ngindent */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngindent; sourceTree = "<group>"; };
FA322D940CEF7523001761B3 /* ngircd.spec */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.spec; sourceTree = "<group>"; }; FA322D940CEF7523001761B3 /* ngircd.spec */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.spec; sourceTree = "<group>"; };
FA322D950CEF7523001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; }; FA322D950CEF7523001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
@@ -196,13 +190,16 @@
FA322DA00CEF752C001761B3 /* RFC.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = RFC.txt; sourceTree = "<group>"; }; FA322DA00CEF752C001761B3 /* RFC.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = RFC.txt; sourceTree = "<group>"; };
FA322DA40CEF752C001761B3 /* Doxyfile */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Doxyfile; sourceTree = "<group>"; }; FA322DA40CEF752C001761B3 /* Doxyfile */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Doxyfile; sourceTree = "<group>"; };
FA322DA50CEF752C001761B3 /* footer.inc.html */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.html; path = footer.inc.html; sourceTree = "<group>"; }; FA322DA50CEF752C001761B3 /* footer.inc.html */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.html; path = footer.inc.html; sourceTree = "<group>"; };
FA322DA60CEF752C001761B3 /* header.inc.html */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.html; path = header.inc.html; sourceTree = "<group>"; };
FA322DA70CEF752C001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; }; FA322DA70CEF752C001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322DA80CEF752C001761B3 /* ngircd-doc.css */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.css; path = "ngircd-doc.css"; sourceTree = "<group>"; };
FA322DA90CEF752C001761B3 /* SSL.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = SSL.txt; sourceTree = "<group>"; }; FA322DA90CEF752C001761B3 /* SSL.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = SSL.txt; sourceTree = "<group>"; };
FA322DAD0CEF7538001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; }; FA322DAD0CEF7538001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322DAE0CEF7538001761B3 /* ngircd.8.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.8.tmpl; sourceTree = "<group>"; }; FA322DAE0CEF7538001761B3 /* ngircd.8.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.8.tmpl; sourceTree = "<group>"; };
FA322DAF0CEF7538001761B3 /* ngircd.conf.5.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.conf.5.tmpl; sourceTree = "<group>"; }; FA322DAF0CEF7538001761B3 /* ngircd.conf.5.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.conf.5.tmpl; sourceTree = "<group>"; };
FA322DB10CEF7565001761B3 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; }; FA322DB10CEF7565001761B3 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
FA322DC00CEF77CB001761B3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; }; FA322DC00CEF77CB001761B3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
FA407F2B0DB159F400271AF1 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = ipaddr/Makefile.am; sourceTree = "<group>"; };
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = ng_ipaddr.c; path = ipaddr/ng_ipaddr.c; sourceTree = "<group>"; }; FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = ng_ipaddr.c; path = ipaddr/ng_ipaddr.c; sourceTree = "<group>"; };
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = ng_ipaddr.h; path = ipaddr/ng_ipaddr.h; sourceTree = "<group>"; }; FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = ng_ipaddr.h; path = ipaddr/ng_ipaddr.h; sourceTree = "<group>"; };
FA407F380DB15AC700271AF1 /* GIT.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = GIT.txt; sourceTree = "<group>"; }; FA407F380DB15AC700271AF1 /* GIT.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = GIT.txt; sourceTree = "<group>"; };
@@ -282,32 +279,28 @@
08FB7794FE84155DC02AAC07 /* ngIRCd */ = { 08FB7794FE84155DC02AAC07 /* ngIRCd */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322D630CEF750F001761B3 /* Makefile.am */,
FA322D660CEF7523001761B3 /* contrib */,
FA322D970CEF752C001761B3 /* doc */, FA322D970CEF752C001761B3 /* doc */,
FA322D660CEF7523001761B3 /* contrib */,
FA322DAB0CEF7538001761B3 /* man */, FA322DAB0CEF7538001761B3 /* man */,
FA322CD40CEF74B0001761B3 /* src */, FA322CD40CEF74B0001761B3 /* src */,
FA322D5A0CEF750F001761B3 /* AUTHORS */, FA322D5A0CEF750F001761B3 /* AUTHORS */,
FA322D5C0CEF750F001761B3 /* ChangeLog */,
FA322D610CEF750F001761B3 /* COPYING */, FA322D610CEF750F001761B3 /* COPYING */,
FA322D620CEF750F001761B3 /* INSTALL */, FA322D620CEF750F001761B3 /* INSTALL */,
FA322D640CEF750F001761B3 /* NEWS */, FA322D640CEF750F001761B3 /* NEWS */,
FA322D650CEF750F001761B3 /* README */, FA322D650CEF750F001761B3 /* README */,
FA322D5B0CEF750F001761B3 /* autogen.sh */, FA322D5B0CEF750F001761B3 /* autogen.sh */,
FA322D5C0CEF750F001761B3 /* ChangeLog */,
FA322D5E0CEF750F001761B3 /* config.guess */, FA322D5E0CEF750F001761B3 /* config.guess */,
FA322D5F0CEF750F001761B3 /* config.sub */, FA322D5F0CEF750F001761B3 /* config.sub */,
FA18A63E16CEDDCE00132F66 /* configure.ng */, FA322D600CEF750F001761B3 /* configure.in */,
FA322D630CEF750F001761B3 /* Makefile.am */,
1AB674ADFE9D54B511CA2CBB /* Products */, 1AB674ADFE9D54B511CA2CBB /* Products */,
FA6BBC651605F6D60004247A /* libiconv.dylib */, FA6BBC651605F6D60004247A /* libiconv.dylib */,
FA2D567A11EA1AB300D37A35 /* libpam.dylib */, FA2D567A11EA1AB300D37A35 /* libpam.dylib */,
FA322DC00CEF77CB001761B3 /* libz.dylib */, FA322DC00CEF77CB001761B3 /* libz.dylib */,
); );
indentWidth = 8;
name = ngIRCd; name = ngIRCd;
sourceTree = "<group>"; sourceTree = "<group>";
tabWidth = 8;
usesTabs = 1;
wrapsLines = 0;
}; };
1AB674ADFE9D54B511CA2CBB /* Products */ = { 1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
@@ -320,12 +313,12 @@
FA322CD40CEF74B0001761B3 /* src */ = { FA322CD40CEF74B0001761B3 /* src */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322CD60CEF74B1001761B3 /* Makefile.am */,
FA407F270DB1598D00271AF1 /* ipaddr */,
FA322CD70CEF74B1001761B3 /* ngircd */, FA322CD70CEF74B1001761B3 /* ngircd */,
FA407F270DB1598D00271AF1 /* ipaddr */,
FA322D0E0CEF74B1001761B3 /* portab */, FA322D0E0CEF74B1001761B3 /* portab */,
FA322D1B0CEF74B1001761B3 /* testsuite */, FA322D1B0CEF74B1001761B3 /* testsuite */,
FA322D2E0CEF74B1001761B3 /* tool */, FA322D2E0CEF74B1001761B3 /* tool */,
FA322CD60CEF74B1001761B3 /* Makefile.am */,
); );
name = src; name = src;
path = ../../src; path = ../../src;
@@ -334,7 +327,7 @@
FA322CD70CEF74B1001761B3 /* ngircd */ = { FA322CD70CEF74B1001761B3 /* ngircd */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64616CEE0DD00132F66 /* Makefile.ng */, FA322D020CEF74B1001761B3 /* Makefile.am */,
FA322CD90CEF74B1001761B3 /* array.c */, FA322CD90CEF74B1001761B3 /* array.c */,
FA322CDA0CEF74B1001761B3 /* array.h */, FA322CDA0CEF74B1001761B3 /* array.h */,
FA322CDB0CEF74B1001761B3 /* channel.c */, FA322CDB0CEF74B1001761B3 /* channel.c */,
@@ -354,10 +347,10 @@
FA6BBC601605F0AC0004247A /* conn-encoding.h */, FA6BBC601605F0AC0004247A /* conn-encoding.h */,
FA322CE10CEF74B1001761B3 /* conn-func.c */, FA322CE10CEF74B1001761B3 /* conn-func.c */,
FA322CE20CEF74B1001761B3 /* conn-func.h */, FA322CE20CEF74B1001761B3 /* conn-func.h */,
FAA3D2790F139CDC00B2447E /* conn-ssl.c */,
FAA3D27A0F139CDC00B2447E /* conn-ssl.h */,
FA322CE30CEF74B1001761B3 /* conn-zip.c */, FA322CE30CEF74B1001761B3 /* conn-zip.c */,
FA322CE40CEF74B1001761B3 /* conn-zip.h */, FA322CE40CEF74B1001761B3 /* conn-zip.h */,
FAA3D2790F139CDC00B2447E /* conn-ssl.c */,
FAA3D27A0F139CDC00B2447E /* conn-ssl.h */,
FA322CE70CEF74B1001761B3 /* defines.h */, FA322CE70CEF74B1001761B3 /* defines.h */,
FA322CE80CEF74B1001761B3 /* hash.c */, FA322CE80CEF74B1001761B3 /* hash.c */,
FA322CE90CEF74B1001761B3 /* hash.h */, FA322CE90CEF74B1001761B3 /* hash.h */,
@@ -375,7 +368,6 @@
FA322CEF0CEF74B1001761B3 /* irc-info.h */, FA322CEF0CEF74B1001761B3 /* irc-info.h */,
FA322CF00CEF74B1001761B3 /* irc-login.c */, FA322CF00CEF74B1001761B3 /* irc-login.c */,
FA322CF10CEF74B1001761B3 /* irc-login.h */, FA322CF10CEF74B1001761B3 /* irc-login.h */,
FA1DBB6716C707D200D4F838 /* irc-macros.h */,
FA4F1659164836B100DBD011 /* irc-metadata.c */, FA4F1659164836B100DBD011 /* irc-metadata.c */,
FA4F165C164836BF00DBD011 /* irc-metadata.h */, FA4F165C164836BF00DBD011 /* irc-metadata.h */,
FA322CF20CEF74B1001761B3 /* irc-mode.c */, FA322CF20CEF74B1001761B3 /* irc-mode.c */,
@@ -420,19 +412,19 @@
FA322D0E0CEF74B1001761B3 /* portab */ = { FA322D0E0CEF74B1001761B3 /* portab */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64716CEE14900132F66 /* Makefile.ng */, FAA3D27C0F139CF800B2447E /* strtok_r.c */,
FAA3D27D0F139CF800B2447E /* waitpid.c */,
FA322D100CEF74B1001761B3 /* ansi2knr.1 */, FA322D100CEF74B1001761B3 /* ansi2knr.1 */,
FA322D110CEF74B1001761B3 /* ansi2knr.c */, FA322D110CEF74B1001761B3 /* ansi2knr.c */,
FA322D120CEF74B1001761B3 /* exp.h */, FA322D120CEF74B1001761B3 /* exp.h */,
FA322D130CEF74B1001761B3 /* imp.h */, FA322D130CEF74B1001761B3 /* imp.h */,
FA322D140CEF74B1001761B3 /* Makefile.am */,
FA322D150CEF74B1001761B3 /* portab.h */, FA322D150CEF74B1001761B3 /* portab.h */,
FA322D160CEF74B1001761B3 /* portabtest.c */, FA322D160CEF74B1001761B3 /* portabtest.c */,
FA322D170CEF74B1001761B3 /* splint.h */, FA322D170CEF74B1001761B3 /* splint.h */,
FA322D180CEF74B1001761B3 /* strdup.c */, FA322D180CEF74B1001761B3 /* strdup.c */,
FA322D190CEF74B1001761B3 /* strlcpy.c */, FA322D190CEF74B1001761B3 /* strlcpy.c */,
FAA3D27C0F139CF800B2447E /* strtok_r.c */,
FA322D1A0CEF74B1001761B3 /* vsnprintf.c */, FA322D1A0CEF74B1001761B3 /* vsnprintf.c */,
FAA3D27D0F139CF800B2447E /* waitpid.c */,
); );
path = portab; path = portab;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -440,33 +432,32 @@
FA322D1B0CEF74B1001761B3 /* testsuite */ = { FA322D1B0CEF74B1001761B3 /* testsuite */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64A16CEE18100132F66 /* Makefile.ng */,
FA322D250CEF74B1001761B3 /* README */,
FA322D1D0CEF74B1001761B3 /* channel-test.e */,
FA322D1E0CEF74B1001761B3 /* check-idle.e */,
FA322D1F0CEF74B1001761B3 /* connect-test.e */,
FAA3D2700F139CB300B2447E /* invite-test.e */, FAA3D2700F139CB300B2447E /* invite-test.e */,
FAA3D2710F139CB300B2447E /* join-test.e */, FAA3D2710F139CB300B2447E /* join-test.e */,
FAA3D2720F139CB300B2447E /* kick-test.e */, FAA3D2720F139CB300B2447E /* kick-test.e */,
FAA3D2730F139CB300B2447E /* message-test.e */, FAA3D2730F139CB300B2447E /* message-test.e */,
FA18A64E16CEE24B00132F66 /* misc-test.e */,
FA18A64C16CEE1AC00132F66 /* mode-test.e */,
FAA3D2760F139CB300B2447E /* opless-channel-test.e */,
FAA3D2770F139CB300B2447E /* server-link-test.e */,
FA322D280CEF74B1001761B3 /* stress-A.e */,
FA322D290CEF74B1001761B3 /* stress-B.e */,
FA1A6BBD0D6857D900AA8F71 /* who-test.e */,
FA18A64D16CEE1D900132F66 /* whois-test.e */,
FA322D200CEF74B1001761B3 /* functions.inc */,
FAA3D2740F139CB300B2447E /* ngircd-test1.conf */, FAA3D2740F139CB300B2447E /* ngircd-test1.conf */,
FAA3D2750F139CB300B2447E /* ngircd-test2.conf */, FAA3D2750F139CB300B2447E /* ngircd-test2.conf */,
FAA3D2760F139CB300B2447E /* opless-channel-test.e */,
FAA3D2770F139CB300B2447E /* server-link-test.e */,
FA322D1D0CEF74B1001761B3 /* channel-test.e */,
FA322D1E0CEF74B1001761B3 /* check-idle.e */,
FA322D1F0CEF74B1001761B3 /* connect-test.e */,
FA322D200CEF74B1001761B3 /* functions.inc */,
FA322D210CEF74B1001761B3 /* getpid.sh */, FA322D210CEF74B1001761B3 /* getpid.sh */,
FA322D220CEF74B1001761B3 /* Makefile.am */,
FA1A6BBC0D6857BB00AA8F71 /* misc-test.e */,
FA322D230CEF74B1001761B3 /* mode-test.e */,
FA322D250CEF74B1001761B3 /* README */,
FA322D260CEF74B1001761B3 /* start-server.sh */, FA322D260CEF74B1001761B3 /* start-server.sh */,
FA322D270CEF74B1001761B3 /* stop-server.sh */, FA322D270CEF74B1001761B3 /* stop-server.sh */,
FA322D280CEF74B1001761B3 /* stress-A.e */,
FA322D290CEF74B1001761B3 /* stress-B.e */,
FA322D2A0CEF74B1001761B3 /* stress-server.sh */, FA322D2A0CEF74B1001761B3 /* stress-server.sh */,
FA322D2B0CEF74B1001761B3 /* test-loop.sh */, FA322D2B0CEF74B1001761B3 /* test-loop.sh */,
FA322D2C0CEF74B1001761B3 /* tests.sh */, FA322D2C0CEF74B1001761B3 /* tests.sh */,
FA322D2D0CEF74B1001761B3 /* wait-tests.sh */, FA322D2D0CEF74B1001761B3 /* wait-tests.sh */,
FA1A6BBD0D6857D900AA8F71 /* who-test.e */,
); );
path = testsuite; path = testsuite;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -474,7 +465,9 @@
FA322D2E0CEF74B1001761B3 /* tool */ = { FA322D2E0CEF74B1001761B3 /* tool */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64F16CEE27700132F66 /* Makefile.ng */, FA322D300CEF74B1001761B3 /* ansi2knr.1 */,
FA322D310CEF74B1001761B3 /* ansi2knr.c */,
FA322D320CEF74B1001761B3 /* Makefile.am */,
FA322D330CEF74B1001761B3 /* tool.c */, FA322D330CEF74B1001761B3 /* tool.c */,
FA322D340CEF74B1001761B3 /* tool.h */, FA322D340CEF74B1001761B3 /* tool.h */,
); );
@@ -484,18 +477,16 @@
FA322D660CEF7523001761B3 /* contrib */ = { FA322D660CEF7523001761B3 /* contrib */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322D8D0CEF7523001761B3 /* Makefile.am */,
FA322D680CEF7523001761B3 /* Debian */, FA322D680CEF7523001761B3 /* Debian */,
FA322D730CEF7523001761B3 /* MacOSX */, FA322D730CEF7523001761B3 /* MacOSX */,
FA322D950CEF7523001761B3 /* README */, FA322D910CEF7523001761B3 /* Makefile.am */,
FA322D920CEF7523001761B3 /* ngindent */, FA322D920CEF7523001761B3 /* ngindent */,
FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */, FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */,
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */, FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */,
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */, FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */,
FA18A63F16CEDE2300132F66 /* ngircd.service */,
FA18A64016CEDE2300132F66 /* ngircd.socket */,
FA322D940CEF7523001761B3 /* ngircd.spec */, FA322D940CEF7523001761B3 /* ngircd.spec */,
FA4B08E813E7F91C00765BA3 /* platformtest.sh */, FA4B08E813E7F91C00765BA3 /* platformtest.sh */,
FA322D950CEF7523001761B3 /* README */,
FA322D960CEF7523001761B3 /* systrace.policy */, FA322D960CEF7523001761B3 /* systrace.policy */,
); );
name = contrib; name = contrib;
@@ -505,14 +496,13 @@
FA322D680CEF7523001761B3 /* Debian */ = { FA322D680CEF7523001761B3 /* Debian */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322D6E0CEF7523001761B3 /* Makefile.am */,
FA322D6A0CEF7523001761B3 /* changelog */, FA322D6A0CEF7523001761B3 /* changelog */,
FA322D6B0CEF7523001761B3 /* compat */, FA322D6B0CEF7523001761B3 /* compat */,
FA322D6C0CEF7523001761B3 /* control */, FA322D6C0CEF7523001761B3 /* control */,
FA322D6D0CEF7523001761B3 /* copyright */, FA322D6D0CEF7523001761B3 /* copyright */,
FA322D6E0CEF7523001761B3 /* Makefile.am */,
FA322D6F0CEF7523001761B3 /* ngircd.default */, FA322D6F0CEF7523001761B3 /* ngircd.default */,
FA322D700CEF7523001761B3 /* ngircd.init */, FA322D700CEF7523001761B3 /* ngircd.init */,
FA18A64116CEDE3500132F66 /* ngircd.pam */,
FA322D710CEF7523001761B3 /* ngircd.postinst */, FA322D710CEF7523001761B3 /* ngircd.postinst */,
FA322D720CEF7523001761B3 /* rules */, FA322D720CEF7523001761B3 /* rules */,
); );
@@ -522,17 +512,88 @@
FA322D730CEF7523001761B3 /* MacOSX */ = { FA322D730CEF7523001761B3 /* MacOSX */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64316CEDE8100132F66 /* Makefile.am */,
FAA3D2810F139D2E00B2447E /* ngIRCd.pmdoc */, FAA3D2810F139D2E00B2447E /* ngIRCd.pmdoc */,
FA322DB10CEF7565001761B3 /* config.h */,
FA18A64216CEDE5700132F66 /* de.barton.ngircd.plist.tmpl */,
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */,
FAA3D28A0F139D2E00B2447E /* postinstall.sh */, FAA3D28A0F139D2E00B2447E /* postinstall.sh */,
FAA3D28B0F139D2E00B2447E /* preinstall.sh */, FAA3D28B0F139D2E00B2447E /* preinstall.sh */,
FA322D750CEF7523001761B3 /* build */,
FA322D8D0CEF7523001761B3 /* Makefile.am */,
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */,
FA322DB10CEF7565001761B3 /* config.h */,
); );
path = MacOSX; path = MacOSX;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
FA322D750CEF7523001761B3 /* build */ = {
isa = PBXGroup;
children = (
FA322D760CEF7523001761B3 /* ngIRCd.build */,
);
path = build;
sourceTree = "<group>";
};
FA322D760CEF7523001761B3 /* ngIRCd.build */ = {
isa = PBXGroup;
children = (
FA322D770CEF7523001761B3 /* Default */,
FA322D7F0CEF7523001761B3 /* ngIRCd.pbxindex */,
);
path = ngIRCd.build;
sourceTree = "<group>";
};
FA322D770CEF7523001761B3 /* Default */ = {
isa = PBXGroup;
children = (
FA322D780CEF7523001761B3 /* ngIRCd.build */,
);
path = Default;
sourceTree = "<group>";
};
FA322D780CEF7523001761B3 /* ngIRCd.build */ = {
isa = PBXGroup;
children = (
FA322D7A0CEF7523001761B3 /* Objects-normal */,
);
path = ngIRCd.build;
sourceTree = "<group>";
};
FA322D7A0CEF7523001761B3 /* Objects-normal */ = {
isa = PBXGroup;
children = (
FA322D7B0CEF7523001761B3 /* i386 */,
FA322D7D0CEF7523001761B3 /* ppc */,
);
path = "Objects-normal";
sourceTree = "<group>";
};
FA322D7B0CEF7523001761B3 /* i386 */ = {
isa = PBXGroup;
children = (
);
path = i386;
sourceTree = "<group>";
};
FA322D7D0CEF7523001761B3 /* ppc */ = {
isa = PBXGroup;
children = (
);
path = ppc;
sourceTree = "<group>";
};
FA322D7F0CEF7523001761B3 /* ngIRCd.pbxindex */ = {
isa = PBXGroup;
children = (
FA322D880CEF7523001761B3 /* strings.pbxstrings */,
);
path = ngIRCd.pbxindex;
sourceTree = "<group>";
};
FA322D880CEF7523001761B3 /* strings.pbxstrings */ = {
isa = PBXGroup;
children = (
);
path = strings.pbxstrings;
sourceTree = "<group>";
};
FA322D8F0CEF7523001761B3 /* Products */ = { FA322D8F0CEF7523001761B3 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -544,10 +605,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322D9B0CEF752C001761B3 /* Makefile.am */, FA322D9B0CEF752C001761B3 /* Makefile.am */,
FA322DA20CEF752C001761B3 /* src */,
FAE22BD215270EA300F1A5AB /* Bopm.txt */, FAE22BD215270EA300F1A5AB /* Bopm.txt */,
FAD5852F15271A7800328741 /* Capabilities.txt */, FAD5852F15271A7800328741 /* Capabilities.txt */,
FA18A64416CEDFCE00132F66 /* Commands.txt */,
FAE22BD415270EA300F1A5AB /* Contributing.txt */, FAE22BD415270EA300F1A5AB /* Contributing.txt */,
FA322D9A0CEF752C001761B3 /* FAQ.txt */, FA322D9A0CEF752C001761B3 /* FAQ.txt */,
FA407F380DB15AC700271AF1 /* GIT.txt */, FA407F380DB15AC700271AF1 /* GIT.txt */,
@@ -563,6 +622,7 @@
FAA3D2800F139D1500B2447E /* Services.txt */, FAA3D2800F139D1500B2447E /* Services.txt */,
FA322DA90CEF752C001761B3 /* SSL.txt */, FA322DA90CEF752C001761B3 /* SSL.txt */,
FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */, FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */,
FA322DA20CEF752C001761B3 /* src */,
); );
name = doc; name = doc;
path = ../../doc; path = ../../doc;
@@ -571,9 +631,11 @@
FA322DA20CEF752C001761B3 /* src */ = { FA322DA20CEF752C001761B3 /* src */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA322DA70CEF752C001761B3 /* Makefile.am */,
FA322DA40CEF752C001761B3 /* Doxyfile */, FA322DA40CEF752C001761B3 /* Doxyfile */,
FA322DA50CEF752C001761B3 /* footer.inc.html */, FA322DA50CEF752C001761B3 /* footer.inc.html */,
FA322DA60CEF752C001761B3 /* header.inc.html */,
FA322DA70CEF752C001761B3 /* Makefile.am */,
FA322DA80CEF752C001761B3 /* ngircd-doc.css */,
); );
path = src; path = src;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -592,7 +654,7 @@
FA407F270DB1598D00271AF1 /* ipaddr */ = { FA407F270DB1598D00271AF1 /* ipaddr */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA18A64516CEE0C700132F66 /* Makefile.ng */, FA407F2B0DB159F400271AF1 /* Makefile.am */,
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */, FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */,
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */, FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */,
); );
@@ -602,12 +664,12 @@
FAA3D2810F139D2E00B2447E /* ngIRCd.pmdoc */ = { FAA3D2810F139D2E00B2447E /* ngIRCd.pmdoc */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FAA3D2880F139D2E00B2447E /* Makefile.am */,
FAA3D2860F139D2E00B2447E /* index.xml */,
FAA3D2830F139D2E00B2447E /* 01ngircd.xml */,
FAA3D2820F139D2E00B2447E /* 01ngircd-contents.xml */, FAA3D2820F139D2E00B2447E /* 01ngircd-contents.xml */,
FAA3D2850F139D2E00B2447E /* 02de.xml */, FAA3D2830F139D2E00B2447E /* 01ngircd.xml */,
FAA3D2840F139D2E00B2447E /* 02de-contents.xml */, FAA3D2840F139D2E00B2447E /* 02de-contents.xml */,
FAA3D2850F139D2E00B2447E /* 02de.xml */,
FAA3D2860F139D2E00B2447E /* index.xml */,
FAA3D2880F139D2E00B2447E /* Makefile.am */,
); );
path = ngIRCd.pmdoc; path = ngIRCd.pmdoc;
sourceTree = "<group>"; sourceTree = "<group>";

View File

@@ -1,6 +1,6 @@
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@ EXTRA_DIST = README \
ngIRCd-Logo.gif \ ngIRCd-Logo.gif \
ngircd-redhat.init \ ngircd-redhat.init \
ngircd.service \ ngircd.service \
ngircd.socket \
ngircd.spec \ ngircd.spec \
platformtest.sh \ platformtest.sh \
systrace.policy systrace.policy

View File

@@ -2,21 +2,18 @@
ngIRCd - Next Generation IRC Server ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/ http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors. (c)2001-2011 Alexander Barton and Contributors.
ngIRCd is free software and published under the ngIRCd is free software and published under the
terms of the GNU General Public License. terms of the GNU General Public License.
-- Contributions -- -- Contributions --
Debian/ Debian/
- Various files for building Debian GNU/Linux packages (".deb's"). - Various files for building Debian GNU/Linux packages (".deb's").
- ngircd.init; ngircd.default: init script for Debian-based systems.
- ngircd.pam: example PAM configuraton.
MacOSX/ MacOSX/
- Project files for XCode, the "project builder" of Apple Mac OS X. - Project files for XCode, the "project builder" of Apple Mac OS X.
- de.barton.ngircd.plist[.tmpl]: launchd(8) property list.
ngindent ngindent
- Script to indent the code of ngIRCd in the "standard way". - Script to indent the code of ngIRCd in the "standard way".
@@ -27,12 +24,6 @@ ngircd-bsd.sh
ngircd-redhat.init ngircd-redhat.init
- Start/stop script for RedHat-based distributions (like CentOS). - Start/stop script for RedHat-based distributions (like CentOS).
ngircd.service
- systemd(8) service unit configuration file.
ngircd.socket
- systemd(8) socket unit configuration file for "socket activation".
ngircd.spec ngircd.spec
- RPM "spec" file. - RPM "spec" file.

View File

@@ -3,8 +3,8 @@ Description=Next Generation IRC Daemon
After=network.target After=network.target
[Service] [Service]
Type=forking # don't daemonize to simplify stuff
ExecStart=/usr/sbin/ngircd ExecStart=/usr/sbin/ngircd -n
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID
[Install] [Install]

View File

@@ -1,11 +0,0 @@
[Unit]
Description=Next Generation IRC Daemon (Socket)
[Socket]
BindIPv6Only=ipv6-only
ListenStream=0.0.0.0:6667
#ListenStream=[::]:6667
IPTOS=low-delay
[Install]
WantedBy=sockets.target

View File

@@ -1,5 +1,5 @@
%define name ngircd %define name ngircd
%define version 21~rc2 %define version 20.2
%define release 1 %define release 1
%define prefix %{_prefix} %define prefix %{_prefix}

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -54,16 +54,6 @@ if [ $? -ne 0 ]; then
cd .. cd ..
fi fi
echo "$NAME: Checking for GIT tree ..."
if [ -d .git ]; then
echo "$NAME: Checking for \"git\" command ..."
git version >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "$NAME: Running \"git clean\" ..."
[ -n "$VERBOSE" ] && git clean -dxf || git clean -dxf >/dev/null
fi
fi
echo "$NAME: Checking for \"./configure\" script ..." echo "$NAME: Checking for \"./configure\" script ..."
if [ ! -e ./configure ]; then if [ ! -e ./configure ]; then
echo "$NAME: Running \"./autogen.sh\" ..." echo "$NAME: Running \"./autogen.sh\" ..."
@@ -109,7 +99,6 @@ if [ -r "Makefile" ]; then
CC=$(grep "^CC = " Makefile | cut -d' ' -f3) CC=$(grep "^CC = " Makefile | cut -d' ' -f3)
$CC --version 2>&1 | grep -i "GCC" >/dev/null $CC --version 2>&1 | grep -i "GCC" >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# GCC, or compiler that mimics GCC
$CC --version 2>&1 | grep -i "Open64" >/dev/null $CC --version 2>&1 | grep -i "Open64" >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
COMPILER="Open64" COMPILER="Open64"
@@ -119,24 +108,12 @@ if [ -r "Makefile" ]; then
COMPILER="gcc $COMPILER" COMPILER="gcc $COMPILER"
fi fi
else else
# Non-GCC compiler case "$CC" in
$CC --version 2>&1 | grep -i "clang" >/dev/null gcc*)
if [ $? -eq 0 ]; then
COMPILER=$($CC --version 2>/dev/null | head -1 \
| cut -d'(' -f1 | cut -d'-' -f1 \
| sed -e 's/version //g' | sed -e 's/Apple /A-/g' \
| sed -e 's/Debian //g' | sed -e 's/LLVM /clang /g')
fi
$CC -version 2>&1 | grep -i "tcc" >/dev/null
if [ $? -eq 0 ]; then
COMPILER=$($CC -version 2>/dev/null | head -1 \
| cut -d'(' -f1 | sed -e 's/version //g')
fi
if [ "$COMPILER" = "unknown" ]; then
v="`$CC --version 2>/dev/null | head -1`" v="`$CC --version 2>/dev/null | head -1`"
[ -z "$v" ] && v="`$CC -version 2>/dev/null | head -1`" [ -n "$v" ] && COMPILER="gcc $v"
[ -n "$v" ] && COMPILER="$v" ;;
fi esac
fi fi
fi fi

View File

@@ -1,991 +0,0 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- Commands.txt --
This file lists all commands available on ngIRCd. It is written in a format
that is human readable as well as machine parseable and therefore can be used
as "help text file" of the daemon.
In short, the daemon reads this file on startup and parses it as following
when an user issues a "HELP <cmd>" command:
1. Search the file for a line "- <cmd>",
2. Output all subsequent lines that start with a TAB (ASCII 9) character
to the client using NOTICE commands, treat lines containing a single "."
after the TAB as empty lines.
3. Break at the first line not starting with a TAB character.
This format allows to have information to each command stored in this file
which will not be sent to an IRC user requesting help which enables us to
have additional annotations stored here which further describe the origin,
implementation details, or limits of the specific command which are not
relevant to an end-user but administrators and developers.
A special "Intro" block is returned to the user when the HELP command is
used without a command name:
- Intro
This is ngIRCd, a server software for Internet Relay Chat (IRC)
networks. You can find more information about ngIRCd on its homepage:
<http://ngircd.barton.de>
.
Use "HELP COMMANDS" to get a list of all available commands and
"HELP <command-name>" to get help for a specific IRC command, for
example "HELP quit" or "HELP privmsg".
Connection Handling Commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- CAP
CAP LS
CAP LIST
CAP REQ <capabilities>
CAP ACK <capabilities>
CAP NAK <capabilities>
CAP CLEAR
CAP END
.
List, request, and clear "IRC Capabilities".
.
Using this command, an IRC client can request additional "IRC
capabilities" during login or later on, which influences the
communication between server and client. Normally, these commands
aren't directly used by humans, but automatically by their client
software. And please note that issuing such commands manually can
irritate the client software used, because of the "non-standard"
behavior of the server!
.
- CAP LS: list all available capabilities.
- CAP LIST: list active capabilities of this connection.
- CAP REQ: Request particular capabilities.
- CAP ACK: Acknowledge a set of capabilities to be enabled/disabled.
- CAP NAK: Reject a set of capabilities.
- CAP CLEAR: Clear all set capabilities.
- CAP END: Indicate end of capability negotiation during login,
ignored in an fully registered session.
Please note that the <capabilities> must be given in a single
parameter but whitespace separated, therefore a command could look
like this: "CAP REQ :capability1 capability2 capability3" for example.
References:
- <http://ircv3.atheme.org/specification/capability-negotiation-3.1>
- <http://ngircd.barton.de/doc/Capabilities.txt>
- doc/Capabilities.txt
- CHARCONV
CHARCONV <client-charset>
.
Set client character set encoding to <client-charset>.
.
After receiving such a command, the server translates all message
data received from the client using the set <client-charset> to the
server encoding (UTF-8), and all message data which is to be sent to
the client from the server encoding (UTF-8) to <client-charset>.
.
This enables older clients and clients using "strange" character sets
to transparently participate in channels and direct messages to
clients using UTF-8, which should be the default today.
References:
- IRC+, <http://ngircd.barton.de/doc/Protocol.txt>
- IRC+, doc/Protocol.txt
- NICK
NICK <nickname>
NICK <nickname> [<hops>]
NICK <nickname> <hops> <username> <host> <servertoken> <usermodes> <realname>
.
Set or change the <nickname> of a client (first form) and register
remote clients (second and third form; servers only).
References:
- RFC 1459, 4.1.2 "Nick message" (old client and server protocol)
- RFC 2812, 3.1.2 "Nick message" (client protocol)
- RFC 2813, 4.1.3 "Nick" (server protocol)
- PASS
PASS <password>
PASS <password> <version> <flags> [<options>]
.
Set a connection <password>. This command must be the first command
sent to the server, even before the NICK/USER or SERVER commands.
.
The first form is used by user sessions or (old) RFC 1459 servers,
the second form is used by RFC 2812 or IRC+ compliant servers and
enables the server to indicate its version and supported protocol
features.
References:
- RFC 1459, 4.1.1 "Password message" (old client and server protocol)
- RFC 2812, 3.1.1 "Password message" (client protocol)
- RFC 2813, 4.1.1 "Password message" (server protocol)
- IRC+, <http://ngircd.barton.de/doc/Protocol.txt>
- IRC+, doc/Protocol.txt
- PING
PING <token> [<target>]
.
Tests the presence of a connection to a client or server.
.
If no <target> has been given, the local server is used. User clients
can only use other servers as <target>, no user clients.
.
A PING message results in a PONG reply containing the <token>, which
can be arbitrary text.
Please note:
The RFCs state that the <token> parameter is used to specify the
origin of the PING command when forwarded in the network, but this
is not the case: the sender is specified using the prefix as usual,
and the parameter is used to identify the PONG reply in practice.
References:
- RFC 2812, 3.7.2 "Ping message"
- PONG
PONG <target> [<token>]
.
Reply to a "PING" command, indicate that the connection is alive.
.
The <token> is the arbitrary text received in the "PING" command and
can be used to identify the correct PONG sent as answer.
.
When the "PONG" command is received from a user session, the <target>
parameter is ignored; otherwise the PONG is forwarded to this client.
References:
- RFC 2812, 3.7.3 "Pong message"
- QUIT
QUIT [<quit-message>]
.
Terminate a user session.
.
When received from a user, the server acknowledges this by sending
an "ERROR" message back to the client and terminates the connection.
.
When a <quit-message> has been given, it is sent to all the channels
that the client is a member of when leaving.
References:
- RFC 2812, 3.1.7 "Quit"
- RFC 2813, 4.1.5 "Quit"
- USER
USER <username> <hostname> <unused> <realname>
.
Register (and authenticate) a new user session with a short <username>
and a human-readable <realname>.
.
The parameter <hostname> is only used when received by an other server
and ignored otherwise; and the parameter <unused> is always ignored.
But both parameters are required on each invocation by the protocol
and can be set to arbitrary characters/text when not used.
.
If <username> contains an "@" character, the full <username> is used
for authentication, but only the first part up to this character is
set as "user name" for this session.
References:
- RFC 2812, 3.1.3 "User message"
- WEBIRC
WEBIRC <password> <username> <hostname> <ip-address>
.
Allow Web-to-IRC gateway software (for example) to set the correct
user name and host name of users instead of their own.
.
It must be the very first command sent to the server, even before
USER and NICK commands!
.
The <password> must be set in the server configuration file to prevent
unauthorized clients to fake their identity; it is an arbitrary string.
References:
- IRC+, <http://ngircd.barton.de/doc/Protocol.txt>
- IRC+, doc/Protocol.txt
General Commands
~~~~~~~~~~~~~~~~
- AWAY
AWAY [<message>]
.
Provides the server with a message to automatically send in reply to a
PRIVMSG directed at the user, but not to a channel they are on.
.
If <message> is omitted, the away status is removed.
References:
- RFC 2812, 4.1 "Away"
- HELP
HELP [<command>]
.
Show help information for a specific IRC <command>. The <command> name
is case-insensitive.
.
Use the command "HELP Commands" to get a list of all available commands.
The HELP command isn't specified by any RFC but implemented by most
daemons. If no help text could be read in, ngIRCd outputs a list of all
implemented commands when receiving a plain "HELP" command as well as
on "HELP Commands".
ngIRCd replies using "NOTICE" commands like ircd 2.10/2.11; other
implementations are using numerics 704, 705, and 706.
- MODE
MODE <nickname> [{+|-}<mode>[<mode>] [{+|-}<mode>[<mode>] [...]]]
MODE <channel> [{+|-}<mode>[<mode>] [<arg> [<arg> [...]]] [{+|-}<mode>[<mode>] [<arg> [<arg> [...]]] [...]]]
.
Set and get user and channel modes.
.
When no mode parameters are given, the currently set user or channel
modes are returned. Otherwise the modes are adjusted accordingly
and the changes will be reported back to the client.
.
All user and channel "modes" are indicated by single case-sensitive
characters.
.
Please note that a user can only get and set his own modes, and not
all user "levels" are allowed to change all channel modes ...
.
The mode parameters can become quite complex, especially when dealing
with channel modes that require additional arguments:
.
{+|-}<mode(s}> -- set or unset one or more modes.
+<mode(s)> -<mode(s)> -- set some modes and unset others.
+<modes> <arg1> <arg2> -- set (at least) two modes with arguments.
.
Some examples:
.
MODE nick +i -- set user to "invisible".
MODE #chan +tn -- set "topic lock" and "no external messages".
MODE #chan -t +l 50 -- remove "topic lock", set "user limit" to 50.
MODE #chan +ov nick1 nick2 -- set "channel op" and "voice" mode
to nick1 and nick2 in channel #chan.
.
A complete list of all modes supported by ngIRCd can be found online
here: <http://ngircd.barton.de/doc/Modes.txt>.
References:
- RFC 2811, 4. "Channel Modes"
- RFC 2812, 3.1.5 "User mode message"
- RFC 2812, 3.2.3 "Channel mode message"
- <http://ngircd.barton.de/doc/Modes.txt>
- doc/Modes.txt
- NOTICE
NOTICE <target>[,<target>[,...]] <message>
.
Send a <message> to a given <target>, which can be a user or a
channel, but DON'T report any error.
.
The "NOTICE" command exactly behaves like the "PRIVMSG" command, but
doesn't report any errors it encounters (like an unknown <target>).
Please see the help text of the "PRIVMSG" command for a detailed
description of the parameters!
References:
- RFC 2812, 2.3.1 "Message format in Augmented BNF"
- RFC 2812, 3.3 "Sending messages"
- RFC 2812, 3.3.2 "Notice"
- PRIVMSG
PRIVMSG <target>[,<target>[,...]] <message>
.
Send a <message> to a given <target>, which can be a user or a
channel, and report all errors.
.
The <target> must follow one of these syntax variants:
.
- <nickname>
- <channel>
- <user>[%<host>]@<server>
- <user>%<host>
- <nickname>!<user>@<host>
.
If the <target> is a user, a private message is sent directly to this
user; if it resolves to a channel name, a public message is sent
to all the members of that channel.
.
In addition, IRC Ops can use these two forms to specify the <target>:
.
- #<hostmask>
- #<servermask>
.
The <mask> can contain the wildcard characters "*" and "?", but must
contain at least one dot (".") and no wildcard after the last one.
Then, the <message> is sent to all users matching this <mask>.
.
All warnings and errors are reported back to the initiator using
numeric status codes, which is the only difference to the "NOTICE"
command, which doesn't report back any errors or warnings at all.
.
Please note that clients often use "MSG" as an alias to PRIVMSG, and
a command "QUERY <nick> [<message>]" to initiate private chats. Both
are command extensions of the client and never sent to the server.
References:
- RFC 2812, 2.3.1 "Message format in Augmented BNF"
- RFC 2812, 3.3 "Sending messages"
- RFC 2812, 3.3.1 "Private messages"
Status and Informational Commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ADMIN
ADMIN [<target>]
.
Show administrative information about an IRC server in the network.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.4.9 "Admin command"
- INFO
INFO [<target>]
.
Show the version, birth & online time of an IRC server in the network.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.4.10 "Info command"
- ISON
ISON <nickname> [<nickname> [...]]
.
Query online status of a list of nicknames. The server replies with
a list only containing nicknames actually connected to a server in
the network. If no nicknames of the given list are online, an empty
list is returned to the client requesting the information.
Please note that "all" IRC daemons even parse separate nicknames in
a single parameter (like ":nick1 nick2"), and therefore ngIRCd
implements this behaviour, too.
References:
- RFC 2812, 4.9 "Ison message"
- LINKS
LINKS [[<target>] [<mask>]
.
List all servers currently registered in the network matching <mask>,
or all servers if <mask> has been omitted, as seen by the server
specified by <target> or the local server when <target> is omitted.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
References:
- RFC 2812, 3.4.5 "Links message"
- LUSERS
LUSERS [<mask> [<target>]]
.
Return statistics about the number of clients (users, servers,
services, ...) in the network as seen by the server <target>.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
Please note that ngIRCd ignores the <mask> parameter entirely: it
is not possible to get information for a part of the network only.
References:
- RFC 2812, 3.4.2 "Lusers message"
- MOTD
MOTD [<target>]
.
Show the "Message of the Day" (MOTD) of an IRC server in the network.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.4.1 "Motd message"
- NAMES
NAMES [<channel>[,<channel>[,...]] [<target>]]
.
Show the list of users that are members of a particular <channel>
(and that are visible for the client requesting this information) as
seen by the server <target>. More than one <channel> can be given
separated by "," (but not whitespaces!).
.
If <channel> has been omitted, all visible users are shown, grouped
by channel name, and all visible users not being members of at least
one channel are shown as members of the pseudo channel "*".
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.2.5 "Names message"
- STATS
STATS [<query> [<target>]]
.
Show statistics and other information of type <query> of a particular
IRC server in the network.
.
The following <query> types are supported (case-insensitive where
applicable):
.
- g Network-wide bans ("G-Lines").
- k Server-local bans ("K-Lines").
- L Link status (servers and user links).
- l Link status (servers and own link).
- m Command usage count.
- u Server uptime.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
.
To use "STATS L" the user must be an IRC Operator.
References:
- RFC 2812, 3.4.4 "Stats message"
- TIME
TIME [<target>]
.
Show the local time of an IRC server in the network.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References
- RFC 2812, 3.4.6 "Time message"
- TRACE
TRACE [<target>]
.
Find the route to a specific server and send information about its
peers. Each server that processes this command reports back to the
sender about it: the replies from pass-through servers form a chain
which shows the route to the destination.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.4.8 "Trace message"
- USERHOST
USERHOST <nickname> [<nickname> [...]]
.
Show flags and the hostmasks (<user>@<host>) of the <nickname>s,
separated by spaces. The following flags are used:
.
- "-" The client is "away" (the mode "+a" is set on this client).
- "+" Client seems to be available, at least it isn't marked "away".
- "*" The client is an IRC operator (the mode "+o" is set).
References:
- RFC 2812, 4.8 "Userhost message"
- VERSION
VERSION [<target>]
.
Show version information about a particular IRC server in the network.
.
<target> can be a server name, the nickname of a client connected to
a specific server, or a mask matching a server name in the network.
The server of the current connection is used when <target> is omitted.
.
Please note: in normal operation, the version number ends in a dot
(".", for example "ngIRCd-20.1."). If it ends in ".1" (for example
"ngIRCd-20.1.1", same version than before!), the server is running in
debug-mode; and if it ends in ".2", the "network sniffer" is active!
Keep your privacy in mind ...
References:
- RFC 2812, 3.4.3 "Version message"
- WHO
WHO [<mask> ["o"]]
.
Show a list of users who match the <mask>, or all visible users when
the <mask> has been omitted. (Special case: the <mask> "0" is
equivalent to "*")
.
If the flag "o" is given, the server will only return information about
IRC Operators.
References:
- RFC 2812, 3.6.1 "Who query"
- WHOIS
WHOIS [<target>] <mask>[,<mask>[,...]]
.
Query information about users matching the <mask> parameter(s) as seen
by the server <target>; up to 3 <masks> are supported.
.
<target> can be a server name, the nickname of a client connected to a
specific server, or a mask matching a server name in the network. The
server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.6.2 "Whois query"
- WHOWAS
WHOWAS <nickname>[,<nickname>[,...]] [<count> [<target>]]
.
Query information about nicknames no longer in use in the network,
either because of nickname changes or disconnects. The history is
searched backwards, returning the most recent entry first. If there
are multiple entries, up to <count> entries will be shown (or all of
them, if no <count> has been given).
.
<target> can be a server name, the nickname of a client connected to a
specific server, or a mask matching a server name in the network. The
server of the current connection is used when <target> is omitted.
References:
- RFC 2812, 3.6.3 "Whowas"
Channel Commands
~~~~~~~~~~~~~~~~
- INVITE
INVITE <nickname> <channel>
.
Invite <nickname> to join channel <channel>.
.
<channel> does not have to exist, but if it does, only members of the
channel are allowed to invite other users. If the channel mode "+i"
is set, only channel "half-ops" (and above) may invite other clients,
and if channel mode "+V" is set, nobody can invite other users.
References:
- RFC 2812, 3.2.7 "Invite message"
- JOIN
JOIN {<channel>[,<channel>[,...]] [<key>[,<key>[,...]]] | 0}
.
Makes the client join the <channel> (comma-separated list), specifying
the channel keys ("passwords"). A <channel-key> is only needed if the
<channel> has the mode "+k" set.
.
If the channel(s) do not exist, then they will be created.
.
Using "JOIN 0" parts all channels at once.
References:
- RFC 2812, 3.2.1 "Join message" (client protocol)
- RFC 2813, 4.2.1 "Join message" (server protocol)
- KICK
KICK <channel>[,<channel>[,...]] <nickname>[,<nickname>[,...]] [<reason>]
.
Remove users(s) with <nickname>(s) from <channel>(s).
.
There must be either exactly one <channel> parameter and multiple
<nickname> parameters, or as many <channel> parameters as there are
<nickname> parameters. The <reason> is shown to the users being
kicked, and the nickname of the current user is used when <reason>
is omitted.
References:
- RFC 2812, 3.2.8 "Kick command"
- LIST
LIST [<channel>[,<channel>[,...]] [<server>]]
.
List all visible <channels> (comma-separated list).
.
If <server> is given, the command will be forwarded to <server> for
evaluation.
References:
- RFC 2812, 3.2.6 "List message"
- PART
PART <channel>[,<channel>[,...]] [<part-message>]
.
Leave <channel> (comma-separated list), optionally with sending a
<part-message> to all the other channel members.
References:
- RFC 2812, 3.2.2 "Part message"
- TOPIC
TOPIC <channel> [<topic>]
.
Change or view the topic of a channel.
.
The topic for channel <channel> is returned if there is no <topic>
given. If the <topic> parameter is present, the topic for that
channel will be changed, if this action is allowed for the user
requesting it. If the <topic> parameter is an empty string, the
topic for that channel will be removed.
References:
- RFC 2812, 3.2.4 "Topic message"
Administrative Commands
~~~~~~~~~~~~~~~~~~~~~~~
- CONNECT
CONNECT <server> [<port> [<remote-server> [<my-pwd> <peer-pwd>]]]
.
Instructs the current server, or <remote-server> if specified,
to connect to the server named <server>, which must be configured
in the server configuration file.
.
To use this command, the user must be an IRC Operator. To establish
a connection on a <remote-server>, you must have remote IRC operator
privileges.
.
If <port>, <my-pwd> and <peer-pwd> are given, these values override
the ones specified in the server configuration file.
References:
- RFC 2812, 3.4.7 "Connect message"
- DIE
DIE [<message>]
.
Instructs the server to shut down.
.
The optional (and non-standard) <message> text is sent to each client
connected to this server before all connections are closed.
.
To use this command, the user must be an IRC Operator.
References:
- RFC 2812, 4.3 "Die message"
- DISCONNECT
DISCONNECT <server>
.
Disconnect and disable a locally linked server.
.
To use this command, the user must be an IRC Operator.
References:
- This command is not specified in the IRC RFCs, it is an extension
of ngIRCd.
- GLINE
GLINE <nick!user@hostmask> [<timeout> :<reason>]
.
This command provides timed G-Lines (network-wide bans).
.
If a client matches a G-Line, it cannot connect to any server on
the IRC network for <timeout> seconds. When <timeout> is 0, it make
the G-Line permanent.
.
If no <timeout> and no <reason> is given, the G-Line is removed.
.
To use this command, the user must be an IRC Operator.
.
"STATS g" can be used to list all currently active G-Lines.
References:
- This command is not specified in the IRC RFCs, it is an extension
of ngIRCd.
- KILL
KILL <nickname> <reason>
.
Forcibly remove all users with a given <nickname> from the IRC
network and display the given <reason> to them.
.
This command is used internally between servers, too, for example
to disconnect duplicate <nickname>'s after a "net split".
.
To use this command, the user must be an IRC Operator.
References:
- RFC 2812, 3.7.1 "Kill message"
- KLINE
KLINE <nick!user@hostmask> [<timeout> :<reason>]
.
This command provides timed K-Lines (server-local bans).
.
If a client matches a K-Line, it cannot connect to this server for
<timeout> seconds. When <timeout> is 0, it makes the K-Line permanent.
.
If no <timeout> and no <reason> is given, the K-Line is removed.
.
To use this command, the user must be an IRC Operator.
.
"STATS k" can be used to list all currently active K-Lines.
References:
- This command is not specified in the IRC RFCs, it is an extension
of ngIRCd.
- OPER
OPER <name> <password>
.
Authenticates a user named <name> as an IRC operator on the current
server/network.
.
This operator <name> must be configured in the server configuration.
.
Please note that <name> is NOT related to a nickname at all!
References:
- RFC 2812, 3.1.4 "Oper message"
- REHASH
REHASH
.
Causes the server to re-read and re-process its configuration file(s).
.
While rehashing, no new connections are accepted, but all already
established connections stay connected.
.
To use this command, the user must be an IRC Operator.
References:
- RFC 2812, 4.2 "Rehash message"
- RESTART
RESTART
.
Restart the server.
.
While restarting, all connections are reset and no new connections
are accepted.
.
To use this command, the user must be an IRC Operator.
References:
- RFC 2812, 4.4 "Restart message"
- WALLOPS
WALLOPS <message>
.
Sends <message> to all users with user mode "+w".
.
To use this command, the user must be an IRC Operator.
References:
- RFC 2812, 4.7 "Operwall message"
IRC Service Commands
~~~~~~~~~~~~~~~~~~~~
- SERVICE
SERVICE <name> <reserved1> <distribution> <type> <reserved2> <info>
SERVICE <name> <servertoken> <distribution> {<type>|+<modes>} <hops> <info>
.
Register a new service in the network.
.
The first form is used by directly linked services and isn't supported
by ngIRCd at the moment. The second form announces services connected
to remote "pseudo-servers" ("services hubs").
.
The <distribution> and <type> parameters are ignored by ngIRCd.
References:
- RFC 2812, 3.1.6 "Service message"
- RFC 2813, 4.1.4 "Service message"
- SERVLIST
SERVLIST [<mask> [<type>]]
.
List all IRC services currently registered in the network.
.
The optional <mask> and <type> parameters can be used to limit the
listing to services matching the <mask> and that are of type <type>.
.
Please note that ngIRCd doesn't use any service types at the moment
and therefore all services are of type "0".
References:
- RFC 2812, 3.5.1 "Servlist message"
- SQUERY
SQUERY <target>[,<target>[,...]] <message>
.
Send a <message> to a given <target> IRC service, and report all
errors.
.
The "SQUERY" command exactly behaves like the "PRIVMSG" command, but
enforces that the <target> of the <message> is an IRC service.
Please see the help text of the "PRIVMSG" command for a detailed
description of the parameters!
.
If a user wants to interact with IRC services, he should use "SQUERY"
instead of "PRIVMSG" or "NOTICE": only "SQUERY makes sure that no
regular user, which uses the nickname of an IRC service, receives
the command in error, for example during a "net split"!
References:
- RFC 2812, 2.3.1 "Message format in Augmented BNF"
- RFC 2812, 3.3 "Sending messages"
- RFC 2812, 3.3.2 "Notice"
- SVSNICK
SVSNICK <oldnick> <newnick>
.
Forcefully change foreign user nicknames. This command is allowed
for servers only.
.
The "SVSNICK" command is forwarded to the server to which the user
with nickname <oldnick> is connected to, which in turn generates a
regular "NICK" command that then is sent to the client, so no special
support in the client software is required.
References:
- ngIRCd GIT commit e3f300d3231f
Server Protocol Commands
~~~~~~~~~~~~~~~~~~~~~~~~
- CHANINFO
CHANINFO <channel> +<modes> [[<key> <limit>] <topic>]
.
CHANINFO is used by servers to inform each other about a channel:
its modes, channel key, user limits and its topic.
.
The CHANINFO command is allowed on server-links only.
References:
- IRC+, <http://ngircd.barton.de/doc/Protocol.txt>
- IRC+, doc/Protocol.txt
- ERROR
ERROR [<message> [<> [...]]]
.
Inform a client or a server about an error condition. The first
parameter, if given, is logged by the server receiving the message,
all other parameters are silently ignored.
.
This command is silently ignored on non-server and non-service links
and shouldn't be used by regular IRC clients.
.
The ERROR message is also sent before terminating a regular client
connection.
References:
- RFC 2812, 3.7.4 "Error message"
- METADATA
METADATA <target> <key> <value>
.
The METADATA command is used on server-links to update "metadata"
information of clients, like the hostname, the info text ("real name"),
or the user name.
.
The METADATA command is allowed on server-links only.
References:
- IRC+, <http://ngircd.barton.de/doc/Protocol.txt>
- IRC+, doc/Protocol.txt
- NJOIN
NJOIN <channel> [<mode>]<nick>[,[<mode>]<nick>[,...]]
.
The NJOIN command is used on server-links to add users with <nick>
and <mode> to a <channel> while peering.
.
The NJOIN command is allowed on server-links only.
References:
- RFC 2813, 4.2.2 "Njoin message"
- SERVER
SERVER <servername> <info>
SERVER <servername> <hopcount> <info>
SERVER <servername> <hopcount> <token> <info>
.
The first form registers the local connection as a new server in the
network, the second (RFC 1459) and third (RFC 2812) form announce a
new remote server in the network.
.
The SERVER command is allowed on unregistered or server-links only.
References:
- RFC 1459, 4.1.4 "Server message"
- RFC 2813, 4.1.2 "Server message"
- SQUIT
SQUIT <server> <comment>
.
Disconnects an IRC Server from the network.
.
This command is used on server-links, but can be used by IRC Operators
to forcefully disconnect servers from the network, too.
References:
- RFC 2812, 3.1.8 "Squit"
- RFC 2813, 4.1.6 "Server quit message"
Dummy Commands
~~~~~~~~~~~~~~
- SUMMON
SUMMON <user> [<target> [<channel>]]
.
This command was intended to call people into IRC who are directly
connected to the terminal console of the IRC server -- but is
deprecated today. Therefore ngIRCd doesn't really implement this
command and always returns an error message, regardless of the
parameters given.
References:
- RFC 2812, 4.5 "Summon message"
- USERS
USERS [<target>]
.
This command was intended to list users directly logged in into the
console of the IRC server -- but is deprecated today. Therefore ngIRCd
doesn't really implement this command and always returns an error
message, regardless of the parameters given.
References:
- RFC 2812, 4.6 "Users"
- GET
GET [...]
.
Fake HTTP GET command. When received, the connection is shut down
immediately again to protect against crazy web browsers ...
References:
- ngIRCd GIT commit 33e8c2480649
- POST
POST [...]
.
Fake HTTP POST command. When received, the connection is shut down
immediately again to protect against crazy web browsers ...
References:
- ngIRCd GIT commit 33e8c2480649

View File

@@ -1,6 +1,6 @@
# #
# ngIRCd -- The Next Generation IRC Daemon # ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors # Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -12,7 +12,6 @@
.tmpl: .tmpl:
$(AM_V_GEN)sed \ $(AM_V_GEN)sed \
-e "s@:ETCDIR:@${sysconfdir}@" \ -e "s@:ETCDIR:@${sysconfdir}@" \
-e "s@:DOCDIR:@${docdir}@" \
<$< >$@ <$< >$@
SUFFIXES = .tmpl SUFFIXES = .tmpl
@@ -20,7 +19,6 @@ SUFFIXES = .tmpl
static_docs = \ static_docs = \
Bopm.txt \ Bopm.txt \
Capabilities.txt \ Capabilities.txt \
Commands.txt \
Contributing.txt \ Contributing.txt \
FAQ.txt \ FAQ.txt \
GIT.txt \ GIT.txt \

View File

@@ -1,8 +1,9 @@
ngIRCd - Next Generation IRC Server ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors. (c)2001-2010 Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the ngIRCd is free software and published under the
terms of the GNU General Public License. terms of the GNU General Public License.
@@ -33,13 +34,3 @@ is running as. Therefore a lot of PAM modules aren't working as expected,
because they need root privileges ("pam_unix", for example)! because they need root privileges ("pam_unix", for example)!
Only PAM modules not(!) requiring root privileges (such as "pam_pgsql", Only PAM modules not(!) requiring root privileges (such as "pam_pgsql",
"pam_mysql", "pam_opendirectory" ...) can be used in conjunction with ngIRCd. "pam_mysql", "pam_opendirectory" ...) can be used in conjunction with ngIRCd.
More Examples:
* Use an own "password file" for ngIRCd:
Note: you can use the htpasswd(1) utility of Apache to manage password
files used by pam_pwdfile, see "man htpasswd"!
/etc/pam.d/ngircd:
auth required pam_pwdfile.so pwdfile=/etc/ngircd/ngircd.passwd

View File

@@ -2,7 +2,7 @@
ngIRCd - Next Generation IRC Server ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/ http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors. (c)2001-2012 Alexander Barton and Contributors.
ngIRCd is free software and published under the ngIRCd is free software and published under the
terms of the GNU General Public License. terms of the GNU General Public License.
@@ -26,7 +26,7 @@ list can be updated. Thanks for your help!
Platform Compiler ngIRCd Date Tester C M T R See Platform Compiler ngIRCd Date Tester C M T R See
--------------------------- ------------ ---------- -------- ------ - - - - --- --------------------------- ------------ ---------- -------- ------ - - - - ---
alpha/unknown/netbsd3.0 gcc 3.3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3) alpha/unknown/netbsd3.0 gcc 3.3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3)
armv6l/unkn./linux-gnueabi gcc 4.7.2 20.2 13-03-08 goetz Y Y Y Y (5) armv6l/unkn./linux-gnueabi gcc 4.4.5 19.1 12-06-04 goetz Y Y Y Y (5)
armv7l/unkn./linux-gnueabi gcc 4.4.3 19.1 12-04-29 goetz Y Y Y Y (5) armv7l/unkn./linux-gnueabi gcc 4.4.3 19.1 12-04-29 goetz Y Y Y Y (5)
hppa/unknown/openbsd3.5 gcc 2.95.3 CVSHEAD 04-05-25 alex Y Y Y Y hppa/unknown/openbsd3.5 gcc 2.95.3 CVSHEAD 04-05-25 alex Y Y Y Y
hppa1.1/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y hppa1.1/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y
@@ -73,14 +73,10 @@ powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y N Y
sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y
sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y
sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y
x86_64/apple/darwin12.3.0 gcc 4.2.1 20.2 13-04-01 alex Y Y Y Y (3) x86_64/apple/darwin12.2.0 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3)
x86_64/apple/darwin13.0.0 A-clang 5.0 21~rc1 13-10-16 alex Y Y Y Y (3)
x86_64/unknown/freebsd8.1 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) x86_64/unknown/freebsd8.1 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3)
x86_64/unkn./freebsd8.1-gnu gcc 4.4.5 19 12-02-26 alex Y Y Y Y (3) x86_64/unkn./freebsd8.1-gnu gcc 4.4.5 19 12-02-26 alex Y Y Y Y (3)
x86_64/unknown/linux-gnu clang 3.2 21~rc1 13-10-16 alex Y Y Y Y (1) x86_64/unknown/linux-gnu gcc 4.4.5 20~rc1 12-02-26 alex Y Y Y Y (1)
x86_64/unknown/linux-gnu gcc 4.4.5 20.2 13-04-01 alex Y Y Y Y (1)
x86_64/unknown/linux-gnu Open64 20.3 13-10-16 goetz Y Y Y Y (1)
x86_64/unknown/linux-gnu tcc 0.9.25 20.3 13-10-16 goetz Y Y Y Y (1)
x86_64/unknown/openbsd4.7 gcc 3.3.5 20~rc1 12-02-26 alex Y Y Y Y (3) x86_64/unknown/openbsd4.7 gcc 3.3.5 20~rc1 12-02-26 alex Y Y Y Y (3)
x86_64/unknown/openbsd4.8 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) x86_64/unknown/openbsd4.8 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3)

View File

@@ -224,10 +224,8 @@ new server link", <serverflag> "M"), even if it doesn't support the given
The following <key> names are defined: The following <key> names are defined:
- "accountname": the account name of a client (can't be empty)
- "certfp": the certificate fingerprint of a client (can't be empty)
- "cloakhost": the cloaked hostname of a client
- "host": the hostname of a client (can't be empty) - "host": the hostname of a client (can't be empty)
- "cloakhost": the cloaked hostname of a client
- "info": info text ("real name") of a client - "info": info text ("real name") of a client
- "user": the user name of a client (can't be empty) - "user": the user name of a client (can't be empty)

View File

@@ -14,7 +14,7 @@ acting as a "regular servers" ("pseudo servers") are supported, either
using the IRC protocol as defined in RFC 1459 or RFC 2812. using the IRC protocol as defined in RFC 1459 or RFC 2812.
Support for Services has been tested using Support for Services has been tested using
- Anope 1.9.8 or later (<http://www.anope.org/>) - Anope 1.9.8 or later (<http://www.anope.org/>; unreleased!)
- Atheme 7.0.2 or later (<http://www.atheme.net>) - Atheme 7.0.2 or later (<http://www.atheme.net>)
- "IRC Services" 5.1.x by Andrew Church (<http://achurch.org/services/>) - "IRC Services" 5.1.x by Andrew Church (<http://achurch.org/services/>)
@@ -44,8 +44,10 @@ Example:
Setting up Anope 1.9.x Setting up Anope 1.9.x
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
Anope 1.9.8 or later (<http://www.anope.org/>) can be used with ngIRCd using Anope 1.9.8 or later (<http://www.anope.org/>; unreleased as of 2012-11-10)
the "ngircd" protocol module. may be used with ngIRCd using the "ngircd" protocol module.
Until Anope 1.9.8 is released, you have to use the sources from the Anope
development GIT tree, see <http://sourceforge.net/projects/anope/develop/>!
At least the following settings have to be tweaked, in addition to all the At least the following settings have to be tweaked, in addition to all the
settings marked as required by Anope: settings marked as required by Anope:

View File

@@ -33,10 +33,6 @@
;AdminInfo2 = Location ;AdminInfo2 = Location
;AdminEMail = admin@irc.server ;AdminEMail = admin@irc.server
# Text file which contains the ngIRCd help text. This file is required
# to display help texts when using the "HELP <cmd>" command.
;HelpFile = :DOCDIR:/Commands.txt
# Info text of the server. This will be shown by WHOIS and # Info text of the server. This will be shown by WHOIS and
# LINKS requests for example. # LINKS requests for example.
Info = Server Info Text Info = Server Info Text
@@ -88,13 +84,6 @@
# to not yet (or no longer) connected servers. # to not yet (or no longer) connected servers.
;ConnectRetry = 60 ;ConnectRetry = 60
# Number of seconds after which the whole daemon should shutdown when
# no connections are left active after handling at least one client
# (0: never, which is the default).
# This can be useful for testing or when ngIRCd is started using
# "socket activation" with systemd(8), for example.
;IdleTimeout = 0
# Maximum number of simultaneous in- and outbound connections the # Maximum number of simultaneous in- and outbound connections the
# server is allowed to accept (0: unlimited): # server is allowed to accept (0: unlimited):
;MaxConnections = 0 ;MaxConnections = 0
@@ -128,12 +117,6 @@
# behavior of ngIRCd. If you want to get started quickly, you most # behavior of ngIRCd. If you want to get started quickly, you most
# probably don't have to make changes here -- they are all optional. # probably don't have to make changes here -- they are all optional.
# List of allowed channel types (channel prefixes) for newly created
# channels on the local server. By default, all supported channel
# types are allowed. Set this variable to the empty string to disallow
# creation of new channels by local clients at all.
;AllowedChannelTypes = #&+
# Are remote IRC operators allowed to control this server, e.g. # Are remote IRC operators allowed to control this server, e.g.
# use commands like CONNECT, SQUIT, DIE, ...? # use commands like CONNECT, SQUIT, DIE, ...?
;AllowRemoteOper = no ;AllowRemoteOper = no
@@ -165,12 +148,7 @@
;ConnectIPv6 = yes ;ConnectIPv6 = yes
;ConnectIPv4 = yes ;ConnectIPv4 = yes
# Default user mode(s) to set on new local clients. Please note that # Do any DNS lookups when a client connects to the server.
# only modes can be set that the client could set on itself, you can't
# set "a" (away) or "o" (IRC Op), for example! Default: none.
;DefaultUserModes = i
# Do DNS lookups when a client connects to the server.
;DNS = yes ;DNS = yes
# Do IDENT lookups if ngIRCd has been compiled with support for it. # Do IDENT lookups if ngIRCd has been compiled with support for it.
@@ -178,10 +156,6 @@
# prepended to their user name. # prepended to their user name.
;Ident = yes ;Ident = yes
# Directory containing configuration snippets (*.conf), that should
# be read in after parsing this configuration file.
;IncludeDir = :ETCDIR:/conf.d
# Enhance user privacy slightly (useful for IRC server on TOR or I2P) # Enhance user privacy slightly (useful for IRC server on TOR or I2P)
# by censoring some information like idle time, logon time, etc. # by censoring some information like idle time, logon time, etc.
;MorePrivacy = no ;MorePrivacy = no
@@ -220,6 +194,9 @@
# character prepended to their respective user names! # character prepended to their respective user names!
;PAMIsOptional = no ;PAMIsOptional = no
# Allow Pre-Defined Channels only (see Section [Channels])
;PredefChannelsOnly = no
# Let ngIRCd send an "authentication PING" when a new client connects, # Let ngIRCd send an "authentication PING" when a new client connects,
# and register this client only after receiving the corresponding # and register this client only after receiving the corresponding
# "PONG" reply. # "PONG" reply.
@@ -248,15 +225,6 @@
# SSL Server Key Certificate # SSL Server Key Certificate
;CertFile = :ETCDIR:/ssl/server-cert.pem ;CertFile = :ETCDIR:/ssl/server-cert.pem
# Select cipher suites allowed for SSL/TLS connections. This defaults
# to HIGH:!aNULL:@STRENGTH (OpenSSL) or SECURE128 (GnuTLS).
# See 'man 1ssl ciphers' (OpenSSL) or 'man 3 gnutls_priority_init'
# (GnuTLS) for details.
# For OpenSSL:
;CipherList = HIGH:!aNULL:@STRENGTH
# For GnuTLS:
;CipherList = SECURE128
# Diffie-Hellman parameters # Diffie-Hellman parameters
;DHFile = :ETCDIR:/ssl/dhparams.pem ;DHFile = :ETCDIR:/ssl/dhparams.pem

View File

@@ -16,55 +16,106 @@
# Project related configuration options # Project related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = ngIRCd PROJECT_NAME = ngIRCd
PROJECT_BRIEF = "Lightweight Internet Relay Chat server"
PROJECT_LOGO = "../../contrib/ngIRCd-Logo.gif" # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = . OUTPUT_DIRECTORY = .
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH = ../.. STRIP_FROM_PATH = ../..
JAVADOC_AUTOBRIEF = YES # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
OPTIMIZE_OUTPUT_FOR_C = YES # will interpret the first line (until the first dot) of a JavaDoc-style
TYPEDEF_HIDES_STRUCT = YES # comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explicit @brief command for a brief description.
TAB_SIZE = 8 JAVADOC_AUTOBRIEF = YES
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Build related configuration options # Build related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES EXTRACT_ALL = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES EXTRACT_STATIC = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory
# hierarchy in the documentation. The default is NO.
SHOW_DIRECTORIES = YES SHOW_DIRECTORIES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# configuration options related to the input files # configuration options related to the input files
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that
# contain documented source files. You may enter file names like "myfile.cpp"
# or directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../../src INPUT = ../../src
INPUT_ENCODING = UTF-8
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES RECURSIVE = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# configuration options related to source browsing # configuration options related to source browsing
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES SOURCE_BROWSER = YES
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = NO STRIP_CODE_COMMENTS = NO
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
REFERENCED_BY_RELATION = YES REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented
# function all documented entities called/used by that function will be listed.
REFERENCES_RELATION = YES REFERENCES_RELATION = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -72,7 +123,19 @@ REFERENCES_RELATION = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
GENERATE_HTML = YES GENERATE_HTML = YES
# The HTML_FOOTER tag can be used to specify a personal HTML footer for each
# generated HTML page. If it is left blank doxygen will generate a standard
# footer.
HTML_FOOTER = footer.inc.html HTML_FOOTER = footer.inc.html
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports JavaScript and
# DHTML is required (for instance Mozilla 1.0+, Firefox Netscape 6.0+,
# Internet explorer 5.0+, Konqueror, or Safari).
HTML_DYNAMIC_SECTIONS = YES HTML_DYNAMIC_SECTIONS = YES
GENERATE_DOCSET = NO GENERATE_DOCSET = NO
@@ -88,6 +151,14 @@ GENERATE_PERLMOD = NO
# Configuration options related to the preprocessor # Configuration options related to the preprocessor
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED = DEBUG ZLIB PAM ZEROCONF CONN_MODULE __client_c__ PREDEFINED = DEBUG ZLIB PAM ZEROCONF CONN_MODULE __client_c__
# -eof- # -eof-

View File

@@ -1,6 +1,6 @@
<hr class="footer"> <hr class="footer">
<p style="text-align: center"> <p>
ngIRCd ngIRCd
<a href="http://ngircd.barton.de/">Homepage</a>, <a href="http://ngircd.barton.de/">Homepage</a>,
<a href="http://ngircd.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git">GIT-Repository</a>, <a href="http://ngircd.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git">GIT-Repository</a>,

View File

@@ -1,7 +1,7 @@
.\" .\"
.\" ngircd(8) manual page template .\" ngircd(8) manual page template
.\" .\"
.TH ngircd 8 "Oct 2013" ngIRCd "ngIRCd Manual" .TH ngircd 8 "Oct 2012" ngIRCd "ngIRCd Manual"
.SH NAME .SH NAME
ngIRCd \- the "next generation" IRC daemon ngIRCd \- the "next generation" IRC daemon
.SH SYNOPSIS .SH SYNOPSIS
@@ -23,15 +23,13 @@ which is a little bit exaggerated:
.IR "lightweight Internet Relay Chat server" .IR "lightweight Internet Relay Chat server"
most probably would have been a better name :-) most probably would have been a better name :-)
.PP .PP
Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, Hurd, IRIX, Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, IRIX,
Linux, Mac OS X, Minix, NetBSD, OpenBSD, Solaris, and Windows with Cygwin. Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
.PP
As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf
there are good chances that it also supports other UNIX-based operating there are good chances that it also supports other UNIX-based operating
systems as well. systems as well. By default, ngIRCd writes diagnostic and informational
.PP messages using the syslog mechanism.
By default ngIRCd logs diagnostic and informational messages using the syslog
mechanism, or writes directly to the console when running in the foreground
(see below).
.SH OPTIONS .SH OPTIONS
The default behavior of The default behavior of
.BR ngircd .BR ngircd

View File

@@ -1,7 +1,7 @@
.\" .\"
.\" ngircd.conf(5) manual page template .\" ngircd.conf(5) manual page template
.\" .\"
.TH ngircd.conf 5 "Oct 2013" ngIRCd "ngIRCd Manual" .TH ngircd.conf 5 "Nov 2012" ngIRCd "ngIRCd Manual"
.SH NAME .SH NAME
ngircd.conf \- configuration file of ngIRCd ngircd.conf \- configuration file of ngIRCd
.SH SYNOPSIS .SH SYNOPSIS
@@ -101,12 +101,6 @@ IRC network and must contain at least one dot (".") character.
Information about the server and the administrator, used by the ADMIN Information about the server and the administrator, used by the ADMIN
command. This information is not required by the server but by RFC! command. This information is not required by the server but by RFC!
.TP .TP
\fBHelpFile\fR (string)
Text file which contains the ngIRCd help text. This file is required
to display help texts when using the "HELP <cmd>" command.
Please note: Changes made to this file take effect when ngircd starts up
or is instructed to re-read its configuration file.
.TP
\fBInfo\fR (string) \fBInfo\fR (string)
Info text of the server. This will be shown by WHOIS and LINKS requests for Info text of the server. This will be shown by WHOIS and LINKS requests for
example. example.
@@ -133,8 +127,8 @@ if ngIRCd is using PAM!
.TP .TP
\fBPidFile\fR (string) \fBPidFile\fR (string)
This tells ngIRCd to write its current process ID to a file. Note that the This tells ngIRCd to write its current process ID to a file. Note that the
"PID file" is written AFTER chroot and switching the user ID, e.g. the directory pidfile is written AFTER chroot and switching the user ID, e.g. the directory
the file resides in must be writable by the ngIRCd user and exist in the the pidfile resides in must be writable by the ngIRCd user and exist in the
chroot directory (if configured, see above). chroot directory (if configured, see above).
.TP .TP
\fBPorts\fR (list of numbers) \fBPorts\fR (list of numbers)
@@ -170,12 +164,6 @@ should be safe, but it is wise to double-check :-)
The server tries every <ConnectRetry> seconds to establish a link to not yet The server tries every <ConnectRetry> seconds to establish a link to not yet
(or no longer) connected servers. Default: 60. (or no longer) connected servers. Default: 60.
.TP .TP
\fBIdleTimeout\fR (number)
Number of seconds after which the whole daemon should shutdown when no
connections are left active after handling at least one client (0: never). This
can be useful for testing or when ngIRCd is started using "socket activation"
with systemd(8), for example. Default: 0.
.TP
\fBMaxConnections\fR (number) \fBMaxConnections\fR (number)
Maximum number of simultaneous in- and outbound connections the server is Maximum number of simultaneous in- and outbound connections the server is
allowed to accept (0: unlimited). Default: 0. allowed to accept (0: unlimited). Default: 0.
@@ -209,12 +197,6 @@ Optional features and configuration options to further tweak the behavior of
ngIRCd. If you want to get started quickly, you most probably don't have to ngIRCd. If you want to get started quickly, you most probably don't have to
make changes here -- they are all optional. make changes here -- they are all optional.
.TP .TP
\fBAllowedChannelTypes\fR (string)
List of allowed channel types (channel prefixes) for newly created channels
on the local server. By default, all supported channel types are allowed.
Set this variable to the empty string to disallow creation of new channels
by local clients at all. Default: #&+
.TP
\fBAllowRemoteOper\fR (boolean) \fBAllowRemoteOper\fR (boolean)
Are IRC operators connected to remote servers allowed to control this server, Are IRC operators connected to remote servers allowed to control this server,
e.g. are they allowed to use administrative commands like CONNECT, DIE, e.g. are they allowed to use administrative commands like CONNECT, DIE,
@@ -258,12 +240,6 @@ Set this to no if you do not want ngIRCd to connect to other IRC servers using
the IPv6 protocol. the IPv6 protocol.
Default: yes. Default: yes.
.TP .TP
\fBDefaultUserModes\fR (string)
Default user mode(s) to set on new local clients. Please note that only modes
can be set that the client could set on itself, you can't set "a" (away) or
"o" (IRC Op), for example!
Default: none.
.TP
\fBDNS\fR (boolean) \fBDNS\fR (boolean)
If set to false, ngIRCd will not make any DNS lookups when clients connect. If set to false, ngIRCd will not make any DNS lookups when clients connect.
If you configure the daemon to connect to other servers, ngIRCd may still If you configure the daemon to connect to other servers, ngIRCd may still
@@ -277,11 +253,6 @@ Users identified using IDENT are registered without the "~" character
prepended to their user name. prepended to their user name.
Default: yes. Default: yes.
.TP .TP
.TP
\fBIncludeDir\fR (string)
Directory containing configuration snippets (*.conf), that should be read in
after parsing the current configuration file.
Default: none.
\fBMorePrivacy\fR (boolean) \fBMorePrivacy\fR (boolean)
This will cause ngIRCd to censor user idle time, logon time as well as the This will cause ngIRCd to censor user idle time, logon time as well as the
part/quit messages (that are sometimes used to inform everyone about which part/quit messages (that are sometimes used to inform everyone about which
@@ -331,6 +302,12 @@ able to distinguish between Ident'ified and PAM-authenticated users: both
don't have a "~" character prepended to their respective user names! don't have a "~" character prepended to their respective user names!
Default: no. Default: no.
.TP .TP
\fBPredefChannelsOnly\fR (boolean)
If enabled, no new channels can be created. Useful if you do not want to have
other channels than those defined in [Channel] sections in the configuration
file on this server.
Default: no.
.TP
\fBRequireAuthPing\fR (boolean) \fBRequireAuthPing\fR (boolean)
Let ngIRCd send an "authentication PING" when a new client connects, and Let ngIRCd send an "authentication PING" when a new client connects, and
register this client only after receiving the corresponding "PONG" reply. register this client only after receiving the corresponding "PONG" reply.
@@ -366,12 +343,6 @@ when it is compiled with support for SSL using OpenSSL or GnuTLS!
\fBCertFile\fR (string) \fBCertFile\fR (string)
SSL Certificate file of the private server key. SSL Certificate file of the private server key.
.TP .TP
\fBCipherList\fR (string)
Select cipher suites allowed for SSL/TLS connections. This defaults to
"HIGH:!aNULL:@STRENGTH" (OpenSSL) or "SECURE128" (GnuTLS).
Please see 'man 1ssl ciphers' (OpenSSL) and 'man 3 gnutls_priority_init'
(GnuTLS) for details.
.TP
\fBDHFile\fR (string) \fBDHFile\fR (string)
Name of the Diffie-Hellman Parameter file. Can be created with GnuTLS Name of the Diffie-Hellman Parameter file. Can be created with GnuTLS
"certtool \-\-generate-dh-params" or "openssl dhparam". If this file is not "certtool \-\-generate-dh-params" or "openssl dhparam". If this file is not

View File

@@ -47,7 +47,6 @@ typedef struct NG_IP_ADDR_DONTUSE ng_ipaddr_t;
static inline int static inline int
ng_ipaddr_af(const ng_ipaddr_t *a) ng_ipaddr_af(const ng_ipaddr_t *a)
{ {
assert(a != NULL);
#ifdef WANT_IPV6 #ifdef WANT_IPV6
return a->sa.sa_family; return a->sa.sa_family;
#else #else
@@ -60,7 +59,6 @@ ng_ipaddr_af(const ng_ipaddr_t *a)
static inline socklen_t static inline socklen_t
ng_ipaddr_salen(const ng_ipaddr_t *a) ng_ipaddr_salen(const ng_ipaddr_t *a)
{ {
assert(a != NULL);
#ifdef WANT_IPV6 #ifdef WANT_IPV6
assert(a->sa.sa_family == AF_INET || a->sa.sa_family == AF_INET6); assert(a->sa.sa_family == AF_INET || a->sa.sa_family == AF_INET6);
if (a->sa.sa_family == AF_INET6) if (a->sa.sa_family == AF_INET6)
@@ -77,14 +75,11 @@ ng_ipaddr_getport(const ng_ipaddr_t *a)
#ifdef WANT_IPV6 #ifdef WANT_IPV6
int af = a->sa.sa_family; int af = a->sa.sa_family;
assert(a != NULL);
assert(af == AF_INET || af == AF_INET6); assert(af == AF_INET || af == AF_INET6);
if (af == AF_INET6) if (af == AF_INET6)
return ntohs(a->sin6.sin6_port); return ntohs(a->sin6.sin6_port);
#endif /* WANT_IPV6 */ #endif /* WANT_IPV6 */
assert(a != NULL);
assert(a->sin4.sin_family == AF_INET); assert(a->sin4.sin_family == AF_INET);
return ntohs(a->sin4.sin_port); return ntohs(a->sin4.sin_port);
} }
@@ -114,15 +109,12 @@ GLOBAL bool ng_ipaddr_tostr_r PARAMS((const ng_ipaddr_t *addr, char *dest));
static inline const char* static inline const char*
ng_ipaddr_tostr(const ng_ipaddr_t *addr) ng_ipaddr_tostr(const ng_ipaddr_t *addr)
{ {
assert(addr != NULL);
return inet_ntoa(addr->sin4.sin_addr); return inet_ntoa(addr->sin4.sin_addr);
} }
static inline bool static inline bool
ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *d) ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *d)
{ {
assert(addr != NULL);
assert(d != NULL);
strlcpy(d, inet_ntoa(addr->sin4.sin_addr), NG_INET_ADDRSTRLEN); strlcpy(d, inet_ntoa(addr->sin4.sin_addr), NG_INET_ADDRSTRLEN);
return true; return true;
} }

View File

@@ -86,7 +86,6 @@ noinst_HEADERS = \
irc-encoding.h \ irc-encoding.h \
irc-info.h \ irc-info.h \
irc-login.h \ irc-login.h \
irc-macros.h \
irc-metadata.h \ irc-metadata.h \
irc-mode.h \ irc-mode.h \
irc-op.h \ irc-op.h \

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -131,11 +131,11 @@ Channel_InitPredefined( void )
new_chan = Channel_Create(conf_chan->name); new_chan = Channel_Create(conf_chan->name);
if (!new_chan) { if (!new_chan) {
Log(LOG_ERR, "Can't create pre-defined channel \"%s\"!", Log(LOG_ERR, "Can't create pre-defined channel \"%s\"",
conf_chan->name); conf_chan->name);
continue; continue;
} }
Log(LOG_INFO, "Created pre-defined channel \"%s\".", Log(LOG_INFO, "Created pre-defined channel \"%s\"",
conf_chan->name); conf_chan->name);
Channel_ModeAdd(new_chan, 'P'); Channel_ModeAdd(new_chan, 'P');
@@ -223,7 +223,7 @@ Channel_Join( CLIENT *Client, const char *Name )
/* Check that the channel name is valid */ /* Check that the channel name is valid */
if (! Channel_IsValidName(Name)) { if (! Channel_IsValidName(Name)) {
IRC_WriteErrClient(Client, ERR_NOSUCHCHANNEL_MSG, IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG,
Client_ID(Client), Name); Client_ID(Client), Name);
return false; return false;
} }
@@ -268,14 +268,14 @@ Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Rea
/* Check that specified channel exists */ /* Check that specified channel exists */
chan = Channel_Search(Name); chan = Channel_Search(Name);
if (!chan) { if (!chan) {
IRC_WriteErrClient(Client, ERR_NOSUCHCHANNEL_MSG, IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG,
Client_ID(Client), Name); Client_ID(Client), Name);
return false; return false;
} }
/* Check that the client is in the channel */ /* Check that the client is in the channel */
if (!Get_Cl2Chan(chan, Client)) { if (!Get_Cl2Chan(chan, Client)) {
IRC_WriteErrClient(Client, ERR_NOTONCHANNEL_MSG, IRC_WriteStrClient(Client, ERR_NOTONCHANNEL_MSG,
Client_ID(Client), Name); Client_ID(Client), Name);
return false; return false;
} }
@@ -299,6 +299,7 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
const char *Reason ) const char *Reason )
{ {
CHANNEL *chan; CHANNEL *chan;
char *ptr, *target_modes;
bool can_kick = false; bool can_kick = false;
assert(Peer != NULL); assert(Peer != NULL);
@@ -309,9 +310,9 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
/* Check that channel exists */ /* Check that channel exists */
chan = Channel_Search( Name ); chan = Channel_Search( Name );
if (!chan) { if( ! chan )
IRC_WriteErrClient(Origin, ERR_NOSUCHCHANNEL_MSG, {
Client_ID(Origin), Name); IRC_WriteStrClient( Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID( Origin ), Name );
return; return;
} }
@@ -319,15 +320,15 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
Client_Type(Origin) != CLIENT_SERVICE) { Client_Type(Origin) != CLIENT_SERVICE) {
/* Check that user is on the specified channel */ /* Check that user is on the specified channel */
if (!Channel_IsMemberOf(chan, Origin)) { if (!Channel_IsMemberOf(chan, Origin)) {
IRC_WriteErrClient(Origin, ERR_NOTONCHANNEL_MSG, IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG,
Client_ID(Origin), Name); Client_ID(Origin), Name);
return; return;
} }
} }
/* Check that the client to be kicked is on the specified channel */ /* Check that the client to be kicked is on the specified channel */
if (!Channel_IsMemberOf(chan, Target)) { if (!Channel_IsMemberOf(chan, Target)) {
IRC_WriteErrClient(Origin, ERR_USERNOTINCHANNEL_MSG, IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG,
Client_ID(Origin), Client_ID(Target), Name ); Client_ID(Origin), Client_ID(Target), Name );
return; return;
} }
@@ -335,43 +336,55 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name,
if(Client_Type(Peer) == CLIENT_USER) { if(Client_Type(Peer) == CLIENT_USER) {
/* Channel mode 'Q' and user mode 'q' on target: nobody but /* Channel mode 'Q' and user mode 'q' on target: nobody but
* IRC Operators and servers can kick the target user */ * IRC Operators and servers can kick the target user */
if ((Channel_HasMode(chan, 'Q') if ((strchr(Channel_Modes(chan), 'Q')
|| Client_HasMode(Target, 'q') || Client_HasMode(Target, 'q')
|| Client_Type(Target) == CLIENT_SERVICE) || Client_Type(Target) == CLIENT_SERVICE)
&& !Client_HasMode(Origin, 'o')) { && !Client_HasMode(Origin, 'o')) {
IRC_WriteErrClient(Origin, ERR_KICKDENY_MSG, IRC_WriteStrClient(Origin, ERR_KICKDENY_MSG,
Client_ID(Origin), Name, Client_ID(Origin), Name,
Client_ID(Target)); Client_ID(Target));
return; return;
} }
/* Check if client has the rights to kick target */ /* Check if client has the rights to kick target */
ptr = Channel_UserModes(chan, Peer);
/* Owner can kick everyone */ target_modes = Channel_UserModes(chan, Target);
if (Channel_UserHasMode(chan, Peer, 'q')) while(*ptr) {
can_kick = true; /* Owner can kick everyone */
if ( *ptr == 'q') {
/* Admin can't kick owner */ can_kick = true;
else if (Channel_UserHasMode(chan, Peer, 'a') && break;
!Channel_UserHasMode(chan, Target, 'q')) }
can_kick = true; /* Admin can't kick owner */
if ( *ptr == 'a' ) {
/* Op can't kick owner | admin */ if (!strchr(target_modes, 'q')) {
else if (Channel_UserHasMode(chan, Peer, 'o') && can_kick = true;
!Channel_UserHasMode(chan, Target, 'q') && break;
!Channel_UserHasMode(chan, Target, 'a')) }
can_kick = true; }
/* Op can't kick owner | admin */
/* Half Op can't kick owner | admin | op */ if ( *ptr == 'o' ) {
else if (Channel_UserHasMode(chan, Peer, 'h') && if (!strchr(target_modes, 'q') &&
!Channel_UserHasMode(chan, Target, 'q') && !strchr(target_modes, 'a')) {
!Channel_UserHasMode(chan, Target, 'a') && can_kick = true;
!Channel_UserHasMode(chan, Target, 'o')) break;
can_kick = true; }
}
/* Half Op can't kick owner | admin | op */
if ( *ptr == 'h' ) {
if (!strchr(target_modes, 'q') &&
!strchr(target_modes, 'a') &&
!strchr(target_modes, 'o')) {
can_kick = true;
break;
}
}
ptr++;
}
if(!can_kick) { if(!can_kick) {
IRC_WriteErrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG, IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG,
Client_ID(Origin), Name); Client_ID(Origin), Name);
return; return;
} }
} }
@@ -420,7 +433,7 @@ Channel_CountVisible (CLIENT *Client)
c = My_Channels; c = My_Channels;
while(c) { while(c) {
if (Client) { if (Client) {
if (!Channel_HasMode(c, 's') if (!strchr(Channel_Modes(c), 's')
|| Channel_IsMemberOf(c, Client)) || Channel_IsMemberOf(c, Client))
count++; count++;
} else } else
@@ -486,14 +499,6 @@ Channel_Modes( CHANNEL *Chan )
} /* Channel_Modes */ } /* Channel_Modes */
GLOBAL bool
Channel_HasMode( CHANNEL *Chan, char Mode )
{
assert( Chan != NULL );
return strchr( Chan->modes, Mode ) != NULL;
} /* Channel_HasMode */
GLOBAL char * GLOBAL char *
Channel_Key( CHANNEL *Chan ) Channel_Key( CHANNEL *Chan )
{ {
@@ -631,7 +636,7 @@ Channel_ModeAdd( CHANNEL *Chan, char Mode )
assert( Chan != NULL ); assert( Chan != NULL );
x[0] = Mode; x[1] = '\0'; x[0] = Mode; x[1] = '\0';
if( ! Channel_HasMode( Chan, x[0] )) if( ! strchr( Chan->modes, x[0] ))
{ {
/* Channel does not have this mode yet, set it */ /* Channel does not have this mode yet, set it */
strlcat( Chan->modes, x, sizeof( Chan->modes )); strlcat( Chan->modes, x, sizeof( Chan->modes ));
@@ -740,13 +745,6 @@ Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
} /* Channel_UserModes */ } /* Channel_UserModes */
GLOBAL bool
Channel_UserHasMode( CHANNEL *Chan, CLIENT *Client, char Mode )
{
return strchr(Channel_UserModes(Chan, Client), Mode) != NULL;
} /* Channel_UserHasMode */
GLOBAL bool GLOBAL bool
Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client ) Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
{ {
@@ -875,15 +873,15 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
if (Channel_IsMemberOf(Chan, From)) { if (Channel_IsMemberOf(Chan, From)) {
is_member = true; is_member = true;
if (Channel_UserHasMode(Chan, From, 'v')) if (strchr(Channel_UserModes(Chan, From), 'v'))
has_voice = true; has_voice = true;
if (Channel_UserHasMode(Chan, From, 'h')) if (strchr(Channel_UserModes(Chan, From), 'h'))
is_halfop = true; is_halfop = true;
if (Channel_UserHasMode(Chan, From, 'o')) if (strchr(Channel_UserModes(Chan, From), 'o'))
is_op = true; is_op = true;
if (Channel_UserHasMode(Chan, From, 'a')) if (strchr(Channel_UserModes(Chan, From), 'a'))
is_chanadmin = true; is_chanadmin = true;
if (Channel_UserHasMode(Chan, From, 'q')) if (strchr(Channel_UserModes(Chan, From), 'q'))
is_owner = true; is_owner = true;
} }
@@ -893,17 +891,17 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
* If channel mode n set: non-members cannot send to channel. * If channel mode n set: non-members cannot send to channel.
* If channel mode m set: need voice. * If channel mode m set: need voice.
*/ */
if (Channel_HasMode(Chan, 'n') && !is_member) if (strchr(Channel_Modes(Chan), 'n') && !is_member)
return false; return false;
if (Channel_HasMode(Chan, 'M') && !Client_HasMode(From, 'R') if (strchr(Channel_Modes(Chan), 'M') && !Client_HasMode(From, 'R')
&& !Client_HasMode(From, 'o')) && !Client_HasMode(From, 'o'))
return false; return false;
if (has_voice || is_halfop || is_op || is_chanadmin || is_owner) if (has_voice || is_halfop || is_op || is_chanadmin || is_owner)
return true; return true;
if (Channel_HasMode(Chan, 'm')) if (strchr(Channel_Modes(Chan), 'm'))
return false; return false;
if (Lists_Check(&Chan->list_excepts, From)) if (Lists_Check(&Chan->list_excepts, From))
@@ -920,20 +918,19 @@ Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Command,
if (!Can_Send_To_Channel(Chan, From)) { if (!Can_Send_To_Channel(Chan, From)) {
if (! SendErrors) if (! SendErrors)
return CONNECTED; /* no error, see RFC 2812 */ return CONNECTED; /* no error, see RFC 2812 */
if (Channel_HasMode(Chan, 'M')) if (strchr(Channel_Modes(Chan), 'M'))
return IRC_WriteErrClient(From, ERR_NEEDREGGEDNICK_MSG, return IRC_WriteStrClient(From, ERR_NEEDREGGEDNICK_MSG,
Client_ID(From), Channel_Name(Chan)); Client_ID(From), Channel_Name(Chan));
else else
return IRC_WriteErrClient(From, ERR_CANNOTSENDTOCHAN_MSG, return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG,
Client_ID(From), Channel_Name(Chan)); Client_ID(From), Channel_Name(Chan));
} }
if (Client_Conn(From) > NONE) if (Client_Conn(From) > NONE)
Conn_UpdateIdle(Client_Conn(From)); Conn_UpdateIdle(Client_Conn(From));
IRC_WriteStrChannelPrefix(Client, Chan, From, true, "%s %s :%s", return IRC_WriteStrChannelPrefix(Client, Chan, From, true,
Command, Channel_Name(Chan), Text); "%s %s :%s", Command, Channel_Name(Chan), Text);
return CONNECTED;
} }
@@ -1092,7 +1089,7 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const ch
} }
/* When channel is empty and is not pre-defined, delete */ /* When channel is empty and is not pre-defined, delete */
if( ! Channel_HasMode( Chan, 'P' )) if( ! strchr( Channel_Modes( Chan ), 'P' ))
{ {
if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan ); if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
} }
@@ -1220,7 +1217,7 @@ Channel_CheckKey(CHANNEL *Chan, CLIENT *Client, const char *Key)
assert(Client != NULL); assert(Client != NULL);
assert(Key != NULL); assert(Key != NULL);
if (!Channel_HasMode(Chan, 'k')) if (!strchr(Chan->modes, 'k'))
return true; return true;
if (*Key == '\0') if (*Key == '\0')
return false; return false;

View File

@@ -79,6 +79,7 @@ GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client )); GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
GLOBAL const char *Channel_Name PARAMS(( const CHANNEL *Chan )); GLOBAL const char *Channel_Name PARAMS(( const CHANNEL *Chan ));
GLOBAL char *Channel_Modes PARAMS(( CHANNEL *Chan ));
GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan )); GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan ));
GLOBAL char *Channel_Key PARAMS(( CHANNEL *Chan )); GLOBAL char *Channel_Key PARAMS(( CHANNEL *Chan ));
GLOBAL unsigned long Channel_MaxUsers PARAMS(( CHANNEL *Chan )); GLOBAL unsigned long Channel_MaxUsers PARAMS(( CHANNEL *Chan ));
@@ -105,12 +106,9 @@ GLOBAL bool Channel_IsValidName PARAMS(( const char *Name ));
GLOBAL bool Channel_ModeAdd PARAMS(( CHANNEL *Chan, char Mode )); GLOBAL bool Channel_ModeAdd PARAMS(( CHANNEL *Chan, char Mode ));
GLOBAL bool Channel_ModeDel PARAMS(( CHANNEL *Chan, char Mode )); GLOBAL bool Channel_ModeDel PARAMS(( CHANNEL *Chan, char Mode ));
GLOBAL bool Channel_HasMode PARAMS(( CHANNEL *Chan, char Mode ));
GLOBAL char *Channel_Modes PARAMS(( CHANNEL *Chan ));
GLOBAL bool Channel_UserModeAdd PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode )); GLOBAL bool Channel_UserModeAdd PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode ));
GLOBAL bool Channel_UserModeDel PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode )); GLOBAL bool Channel_UserModeDel PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode ));
GLOBAL bool Channel_UserHasMode PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode ));
GLOBAL char *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client )); GLOBAL char *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client ));
GLOBAL bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client )); GLOBAL bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client ));

View File

@@ -33,6 +33,8 @@
struct list_head My_Classes[CLASS_COUNT]; struct list_head My_Classes[CLASS_COUNT];
char Reject_Reason[COMMAND_LEN];
GLOBAL void GLOBAL void
Class_Init(void) Class_Init(void)
{ {
@@ -47,29 +49,32 @@ Class_Exit(void)
for (i = 0; i < CLASS_COUNT; Lists_Free(&My_Classes[i++])); for (i = 0; i < CLASS_COUNT; Lists_Free(&My_Classes[i++]));
} }
GLOBAL bool GLOBAL char *
Class_GetMemberReason(const int Class, CLIENT *Client, char *reason, size_t len) Class_GetMemberReason(const int Class, CLIENT *Client)
{ {
char str[COMMAND_LEN] = "listed"; char *reason;
assert(Class < CLASS_COUNT); assert(Class < CLASS_COUNT);
assert(Client != NULL); assert(Client != NULL);
if (!Lists_CheckReason(&My_Classes[Class], Client, str, sizeof(str))) reason = Lists_CheckReason(&My_Classes[Class], Client);
return false; if (!reason)
return NULL;
if (!*reason)
reason = "listed";
switch(Class) { switch(Class) {
case CLASS_GLINE: case CLASS_GLINE:
snprintf(reason, len, "\"%s\" (G-Line)", str); snprintf(Reject_Reason, sizeof(Reject_Reason),
break; "\"%s\" (G-Line)", reason);
return Reject_Reason;
case CLASS_KLINE: case CLASS_KLINE:
snprintf(reason, len, "\"%s\" (K-Line)", str); snprintf(Reject_Reason, sizeof(Reject_Reason),
break; "\"%s\" (K-Line)", reason);
default: return Reject_Reason;
snprintf(reason, len, "%s", str);
break;
} }
return true; return reason;
} }
/** /**
@@ -83,13 +88,15 @@ Class_GetMemberReason(const int Class, CLIENT *Client, char *reason, size_t len)
GLOBAL bool GLOBAL bool
Class_HandleServerBans(CLIENT *Client) Class_HandleServerBans(CLIENT *Client)
{ {
char reject[COMMAND_LEN]; char *rejectptr;
assert(Client != NULL); assert(Client != NULL);
if (Class_GetMemberReason(CLASS_GLINE, Client, reject, sizeof(reject)) || rejectptr = Class_GetMemberReason(CLASS_GLINE, Client);
Class_GetMemberReason(CLASS_KLINE, Client, reject, sizeof(reject))) { if (!rejectptr)
Client_Reject(Client, reject, true); rejectptr = Class_GetMemberReason(CLASS_KLINE, Client);
if (rejectptr) {
Client_Reject(Client, rejectptr, true);
return DISCONNECTED; return DISCONNECTED;
} }
@@ -98,30 +105,24 @@ Class_HandleServerBans(CLIENT *Client)
GLOBAL bool GLOBAL bool
Class_AddMask(const int Class, const char *Pattern, time_t ValidUntil, Class_AddMask(const int Class, const char *Mask, time_t ValidUntil,
const char *Reason) const char *Reason)
{ {
char mask[MASK_LEN];
assert(Class < CLASS_COUNT); assert(Class < CLASS_COUNT);
assert(Pattern != NULL); assert(Mask != NULL);
assert(Reason != NULL); assert(Reason != NULL);
Lists_MakeMask(Pattern, mask, sizeof(mask)); return Lists_Add(&My_Classes[Class], Lists_MakeMask(Mask),
return Lists_Add(&My_Classes[Class], mask,
ValidUntil, Reason); ValidUntil, Reason);
} }
GLOBAL void GLOBAL void
Class_DeleteMask(const int Class, const char *Pattern) Class_DeleteMask(const int Class, const char *Mask)
{ {
char mask[MASK_LEN];
assert(Class < CLASS_COUNT); assert(Class < CLASS_COUNT);
assert(Pattern != NULL); assert(Mask != NULL);
Lists_MakeMask(Pattern, mask, sizeof(mask)); Lists_Del(&My_Classes[Class], Lists_MakeMask(Mask));
Lists_Del(&My_Classes[Class], mask);
} }
GLOBAL struct list_head * GLOBAL struct list_head *

View File

@@ -25,12 +25,11 @@
GLOBAL void Class_Init PARAMS((void)); GLOBAL void Class_Init PARAMS((void));
GLOBAL void Class_Exit PARAMS((void)); GLOBAL void Class_Exit PARAMS((void));
GLOBAL bool Class_AddMask PARAMS((const int Class, const char *Pattern, GLOBAL bool Class_AddMask PARAMS((const int Class, const char *Mask,
const time_t ValidUntil, const char *Reason)); const time_t ValidUntil, const char *Reason));
GLOBAL void Class_DeleteMask PARAMS((const int Class, const char *Pattern)); GLOBAL void Class_DeleteMask PARAMS((const int Class, const char *Mask));
GLOBAL bool Class_GetMemberReason PARAMS((const int Class, CLIENT *Client, GLOBAL char *Class_GetMemberReason PARAMS((const int Class, CLIENT *Client));
char *reason, size_t len));
GLOBAL bool Class_HandleServerBans PARAMS((CLIENT *Client)); GLOBAL bool Class_HandleServerBans PARAMS((CLIENT *Client));
GLOBAL struct list_head *Class_GetList PARAMS((const int Class)); GLOBAL struct list_head *Class_GetList PARAMS((const int Class));

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -41,7 +41,6 @@
#include "hash.h" #include "hash.h"
#include "irc-write.h" #include "irc-write.h"
#include "log.h" #include "log.h"
#include "match.h"
#include "messages.h" #include "messages.h"
#include <exp.h> #include <exp.h>
@@ -62,8 +61,6 @@ static CLIENT *New_Client_Struct PARAMS(( void ));
static void Generate_MyToken PARAMS(( CLIENT *Client )); static void Generate_MyToken PARAMS(( CLIENT *Client ));
static void Adjust_Counters PARAMS(( CLIENT *Client )); static void Adjust_Counters PARAMS(( CLIENT *Client ));
static void Free_Client PARAMS(( CLIENT **Client ));
static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer, static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
CLIENT *TopServer, int Type, const char *ID, CLIENT *TopServer, int Type, const char *ID,
const char *User, const char *Hostname, const char *Info, const char *User, const char *Hostname, const char *Info,
@@ -89,7 +86,7 @@ Client_Init( void )
exit( 1 ); exit( 1 );
} }
/* Client structure for this server */ /* Client-Struktur dieses Servers */
This_Server->next = NULL; This_Server->next = NULL;
This_Server->type = CLIENT_SERVER; This_Server->type = CLIENT_SERVER;
This_Server->conn_id = NONE; This_Server->conn_id = NONE;
@@ -122,15 +119,14 @@ Client_Exit( void )
cnt = 0; cnt = 0;
c = My_Clients; c = My_Clients;
while(c) { while( c )
{
cnt++; cnt++;
next = (CLIENT *)c->next; next = (CLIENT *)c->next;
Free_Client(&c); free( c );
c = next; c = next;
} }
if (cnt) if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
Log(LOG_INFO, "Freed %d client structure%s.",
cnt, cnt == 1 ? "" : "s");
} /* Client_Exit */ } /* Client_Exit */
@@ -220,8 +216,8 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
if (Type == CLIENT_SERVER) if (Type == CLIENT_SERVER)
Generate_MyToken(client); Generate_MyToken(client);
if (Client_HasMode(client, 'a')) if (strchr(client->modes, 'a'))
client->away = strndup(DEFAULT_AWAY_MSG, CLIENT_AWAY_LEN - 1); strlcpy(client->away, DEFAULT_AWAY_MSG, sizeof(client->away));
client->next = (POINTER *)My_Clients; client->next = (POINTER *)My_Clients;
My_Clients = client; My_Clients = client;
@@ -238,14 +234,14 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
/* remove a client */ /* remove a client */
CLIENT *last, *c; CLIENT *last, *c;
char msg[COMMAND_LEN]; char msg[LINE_LEN];
const char *txt; const char *txt;
assert( Client != NULL ); assert( Client != NULL );
txt = LogMsg ? LogMsg : FwdMsg; if( LogMsg ) txt = LogMsg;
if (!txt) else txt = FwdMsg;
txt = "Reason unknown"; if( ! txt ) txt = "Reason unknown.";
/* netsplit message */ /* netsplit message */
if( Client->type == CLIENT_SERVER ) { if( Client->type == CLIENT_SERVER ) {
@@ -285,15 +281,10 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
Destroy_UserOrService(c, txt, FwdMsg, SendQuit); Destroy_UserOrService(c, txt, FwdMsg, SendQuit);
else if( c->type == CLIENT_SERVER ) else if( c->type == CLIENT_SERVER )
{ {
if (c != This_Server) { if( c != This_Server )
if (c->conn_id != NONE) {
Log(LOG_NOTICE|LOG_snotice, if( c->conn_id != NONE ) Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
"Server \"%s\" unregistered (connection %d): %s.", else Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered: %s", c->id, txt );
c->id, c->conn_id, txt);
else
Log(LOG_NOTICE|LOG_snotice,
"Server \"%s\" unregistered: %s.",
c->id, txt);
} }
/* inform other servers */ /* inform other servers */
@@ -305,23 +296,17 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
} }
else else
{ {
if (c->conn_id != NONE) { if( c->conn_id != NONE )
if (c->id[0]) {
Log(LOG_NOTICE, if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
"Client \"%s\" unregistered (connection %d): %s.", else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt );
c->id, c->conn_id, txt);
else
Log(LOG_NOTICE,
"Client unregistered (connection %d): %s.",
c->conn_id, txt);
} else { } else {
Log(LOG_WARNING, Log(LOG_WARNING, "Unregistered unknown client \"%s\": %s",
"Unregistered unknown client \"%s\": %s", c->id[0] ? c->id : "(No Nick)", txt );
c->id[0] ? c->id : "(No Nick)", txt);
} }
} }
Free_Client(&c); free( c );
break; break;
} }
last = c; last = c;
@@ -363,27 +348,6 @@ Client_SetHostname( CLIENT *Client, const char *Hostname )
} /* Client_SetHostname */ } /* Client_SetHostname */
/**
* Set IP address to display for a client.
*
* @param Client The client.
* @param IPAText Textual representation of the IP address or NULL to unset.
*/
GLOBAL void
Client_SetIPAText(CLIENT *Client, const char *IPAText)
{
assert(Client != NULL);
if (Client->ipa_text)
free(Client->ipa_text);
if (*IPAText)
Client->ipa_text = strndup(IPAText, CLIENT_HOST_LEN - 1);
else
Client->ipa_text = NULL;
}
GLOBAL void GLOBAL void
Client_SetID( CLIENT *Client, const char *ID ) Client_SetID( CLIENT *Client, const char *ID )
{ {
@@ -476,22 +440,6 @@ Client_SetFlags( CLIENT *Client, const char *Flags )
} /* Client_SetFlags */ } /* Client_SetFlags */
GLOBAL void
Client_SetAccountName(CLIENT *Client, const char *AccountName)
{
assert(Client != NULL);
if (Client->account_name)
free(Client->account_name);
if (*AccountName)
Client->account_name = strndup(AccountName,
CLIENT_NICK_LEN - 1);
else
Client->account_name = NULL;
}
GLOBAL void GLOBAL void
Client_SetAway( CLIENT *Client, const char *Txt ) Client_SetAway( CLIENT *Client, const char *Txt )
{ {
@@ -500,11 +448,7 @@ Client_SetAway( CLIENT *Client, const char *Txt )
assert( Client != NULL ); assert( Client != NULL );
assert( Txt != NULL ); assert( Txt != NULL );
if (Client->away) strlcpy( Client->away, Txt, sizeof( Client->away ));
free(Client->away);
Client->away = strndup(Txt, CLIENT_AWAY_LEN - 1);
LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client), LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client),
Client_Mask(Client), Txt); Client_Mask(Client), Txt);
} /* Client_SetAway */ } /* Client_SetAway */
@@ -545,11 +489,19 @@ Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
} /* Client_SetIntroducer */ } /* Client_SetIntroducer */
GLOBAL void
Client_SetOperByMe( CLIENT *Client, bool OperByMe )
{
assert( Client != NULL );
Client->oper_by_me = OperByMe;
} /* Client_SetOperByMe */
GLOBAL bool GLOBAL bool
Client_ModeAdd( CLIENT *Client, char Mode ) Client_ModeAdd( CLIENT *Client, char Mode )
{ {
/* Set Mode. /* Set Mode.
* If Client already had Mode, return false. * If Client already alread had Mode, return false.
* If the Mode was newly set, return true. * If the Mode was newly set, return true.
*/ */
@@ -558,7 +510,7 @@ Client_ModeAdd( CLIENT *Client, char Mode )
assert( Client != NULL ); assert( Client != NULL );
x[0] = Mode; x[1] = '\0'; x[0] = Mode; x[1] = '\0';
if (!Client_HasMode(Client, x[0])) { if (!strchr( Client->modes, x[0])) {
strlcat( Client->modes, x, sizeof( Client->modes )); strlcat( Client->modes, x, sizeof( Client->modes ));
return true; return true;
} }
@@ -593,14 +545,13 @@ Client_ModeDel( CLIENT *Client, char Mode )
} /* Client_ModeDel */ } /* Client_ModeDel */
/**
* Search CLIENT structure of a given nick name.
*
* @return Pointer to CLIENT structure or NULL if not found.
*/
GLOBAL CLIENT * GLOBAL CLIENT *
Client_Search( const char *Nick ) Client_Search( const char *Nick )
{ {
/* return Client-Structure that has the corresponding Nick.
* If none is found, return NULL.
*/
char search_id[CLIENT_ID_LEN], *ptr; char search_id[CLIENT_ID_LEN], *ptr;
CLIENT *c = NULL; CLIENT *c = NULL;
UINT32 search_hash; UINT32 search_hash;
@@ -621,39 +572,7 @@ Client_Search( const char *Nick )
c = (CLIENT *)c->next; c = (CLIENT *)c->next;
} }
return NULL; return NULL;
} } /* Client_Search */
/**
* Search first CLIENT structure matching a given mask of a server.
*
* The order of servers is arbitrary, but this function makes sure that the
* local server is always returned if the mask matches it.
*
* @return Pointer to CLIENT structure or NULL if no server could be found.
*/
GLOBAL CLIENT *
Client_SearchServer(const char *Mask)
{
CLIENT *c;
assert(Mask != NULL);
/* First check if mask matches the local server */
if (MatchCaseInsensitive(Mask, Client_ID(Client_ThisServer())))
return Client_ThisServer();
c = My_Clients;
while (c) {
if (Client_Type(c) == CLIENT_SERVER) {
/* This is a server: check if Mask matches */
if (MatchCaseInsensitive(Mask, c->id))
return c;
}
c = (CLIENT *)c->next;
}
return NULL;
}
/** /**
@@ -780,6 +699,8 @@ Client_HostnameCloaked(CLIENT *Client)
* Get (potentially cloaked) hostname of a client to display it to other users. * Get (potentially cloaked) hostname of a client to display it to other users.
* *
* If the client has not enabled cloaking, the real hostname is used. * If the client has not enabled cloaking, the real hostname is used.
* Please note that this function uses a global static buffer, so you can't
* nest invocations without overwriting earlier results!
* *
* @param Client Pointer to client structure * @param Client Pointer to client structure
* @return Pointer to client hostname * @return Pointer to client hostname
@@ -794,28 +715,13 @@ Client_HostnameDisplayed(CLIENT *Client)
return Client_Hostname(Client); return Client_Hostname(Client);
/* Use an already saved cloaked hostname, if there is one */ /* Use an already saved cloaked hostname, if there is one */
if (Client->cloaked) if (Client->cloaked[0])
return Client->cloaked; return Client->cloaked;
Client_UpdateCloakedHostname(Client, NULL, NULL); Client_UpdateCloakedHostname(Client, NULL, NULL);
return Client->cloaked; return Client->cloaked;
} }
GLOBAL const char *
Client_IPAText(CLIENT *Client)
{
assert(Client != NULL);
/* Not a local client? */
if (Client_Conn(Client) <= NONE)
return "0.0.0.0";
if (!Client->ipa_text)
return Conn_GetIPAInfo(Client_Conn(Client));
else
return Client->ipa_text;
}
/** /**
* Update (and generate, if necessary) the cloaked hostname of a client. * Update (and generate, if necessary) the cloaked hostname of a client.
* *
@@ -830,32 +736,25 @@ GLOBAL void
Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin, Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin,
const char *Hostname) const char *Hostname)
{ {
char Cloak_Buffer[CLIENT_HOST_LEN]; static char Cloak_Buffer[CLIENT_HOST_LEN];
assert(Client != NULL); assert(Client != NULL);
if (!Origin) if (!Origin)
Origin = Client_ThisServer(); Origin = Client_ThisServer();
if (!Client->cloaked) {
Client->cloaked = malloc(CLIENT_HOST_LEN);
if (!Client->cloaked)
return;
}
if (!Hostname) { if (!Hostname) {
/* Generate new cloaked hostname */ /* Generate new cloaked hostname */
if (*Conf_CloakHostModeX) { if (*Conf_CloakHostModeX) {
strlcpy(Cloak_Buffer, Client->host, strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
sizeof(Cloak_Buffer));
strlcat(Cloak_Buffer, Conf_CloakHostSalt, strlcat(Cloak_Buffer, Conf_CloakHostSalt,
sizeof(Cloak_Buffer)); CLIENT_HOST_LEN);
snprintf(Client->cloaked, CLIENT_HOST_LEN, snprintf(Client->cloaked, sizeof(Client->cloaked),
Conf_CloakHostModeX, Hash(Cloak_Buffer)); Conf_CloakHostModeX, Hash(Cloak_Buffer));
} else } else
strlcpy(Client->cloaked, Client_ID(Client->introducer), strlcpy(Client->cloaked, Client_ID(Client->introducer),
CLIENT_HOST_LEN); sizeof(Client->cloaked));
} else } else
strlcpy(Client->cloaked, Hostname, CLIENT_HOST_LEN); strlcpy(Client->cloaked, Hostname, sizeof(Client->cloaked));
LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"", LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"",
Client_ID(Client), Client->cloaked); Client_ID(Client), Client->cloaked);
@@ -881,6 +780,14 @@ Client_Flags( CLIENT *Client )
} /* Client_Flags */ } /* Client_Flags */
GLOBAL bool
Client_OperByMe( CLIENT *Client )
{
assert( Client != NULL );
return Client->oper_by_me;
} /* Client_OperByMe */
GLOBAL int GLOBAL int
Client_Hops( CLIENT *Client ) Client_Hops( CLIENT *Client )
{ {
@@ -998,14 +905,6 @@ Client_HasMode( CLIENT *Client, char Mode )
} /* Client_HasMode */ } /* Client_HasMode */
GLOBAL bool
Client_HasFlag( CLIENT *Client, char Flag )
{
assert( Client != NULL );
return strchr( Client->flags, Flag ) != NULL;
} /* Client_HasFlag */
GLOBAL char * GLOBAL char *
Client_Away( CLIENT *Client ) Client_Away( CLIENT *Client )
{ {
@@ -1014,14 +913,6 @@ Client_Away( CLIENT *Client )
} /* Client_Away */ } /* Client_Away */
GLOBAL char *
Client_AccountName(CLIENT *Client)
{
assert(Client != NULL);
return Client->account_name;
}
/** /**
* Make sure that a given nickname is valid. * Make sure that a given nickname is valid.
* *
@@ -1040,11 +931,11 @@ Client_CheckNick(CLIENT *Client, char *Nick)
if (!Client_IsValidNick(Nick)) { if (!Client_IsValidNick(Nick)) {
if (strlen(Nick ) >= Conf_MaxNickLength) if (strlen(Nick ) >= Conf_MaxNickLength)
IRC_WriteErrClient(Client, ERR_NICKNAMETOOLONG_MSG, IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG,
Client_ID(Client), Nick, Client_ID(Client), Nick,
Conf_MaxNickLength - 1); Conf_MaxNickLength - 1);
else else
IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG, IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
Client_ID(Client), Nick); Client_ID(Client), Nick);
return false; return false;
} }
@@ -1053,7 +944,7 @@ Client_CheckNick(CLIENT *Client, char *Nick)
&& Client_Type(Client) != CLIENT_SERVICE) { && Client_Type(Client) != CLIENT_SERVICE) {
/* Make sure that this isn't a restricted/forbidden nickname */ /* Make sure that this isn't a restricted/forbidden nickname */
if (Conf_NickIsBlocked(Nick)) { if (Conf_NickIsBlocked(Nick)) {
IRC_WriteErrClient(Client, ERR_FORBIDDENNICKNAME_MSG, IRC_WriteStrClient(Client, ERR_FORBIDDENNICKNAME_MSG,
Client_ID(Client), Nick); Client_ID(Client), Nick);
return false; return false;
} }
@@ -1061,7 +952,7 @@ Client_CheckNick(CLIENT *Client, char *Nick)
/* Nickname already registered? */ /* Nickname already registered? */
if (Client_Search(Nick)) { if (Client_Search(Nick)) {
IRC_WriteErrClient(Client, ERR_NICKNAMEINUSE_MSG, IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
Client_ID(Client), Nick); Client_ID(Client), Nick);
return false; return false;
} }
@@ -1082,8 +973,7 @@ Client_CheckID( CLIENT *Client, char *ID )
/* ID too long? */ /* ID too long? */
if (strlen(ID) > CLIENT_ID_LEN) { if (strlen(ID) > CLIENT_ID_LEN) {
IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG, IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID(Client), ID);
Client_ID(Client), ID);
return false; return false;
} }
@@ -1181,8 +1071,7 @@ Client_OperCount( void )
c = My_Clients; c = My_Clients;
while( c ) while( c )
{ {
if (c && c->type == CLIENT_USER && Client_HasMode(c, 'o' )) if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
cnt++;
c = (CLIENT *)c->next; c = (CLIENT *)c->next;
} }
return cnt; return cnt;
@@ -1389,14 +1278,11 @@ MyCount( CLIENT_TYPE Type )
} /* MyCount */ } /* MyCount */
/**
* Allocate and initialize new CLIENT strcuture.
*
* @return Pointer to CLIENT structure or NULL on error.
*/
static CLIENT * static CLIENT *
New_Client_Struct( void ) New_Client_Struct( void )
{ {
/* Neue CLIENT-Struktur pre-initialisieren */
CLIENT *c; CLIENT *c;
c = (CLIENT *)malloc( sizeof( CLIENT )); c = (CLIENT *)malloc( sizeof( CLIENT ));
@@ -1410,34 +1296,14 @@ New_Client_Struct( void )
c->type = CLIENT_UNKNOWN; c->type = CLIENT_UNKNOWN;
c->conn_id = NONE; c->conn_id = NONE;
c->oper_by_me = false;
c->hops = -1; c->hops = -1;
c->token = -1; c->token = -1;
c->mytoken = -1; c->mytoken = -1;
return c; return c;
} } /* New_Client */
/**
* Free a CLIENT structure and its member variables.
*/
static void
Free_Client(CLIENT **Client)
{
assert(Client != NULL);
assert(*Client != NULL);
if ((*Client)->account_name)
free((*Client)->account_name);
if ((*Client)->away)
free((*Client)->away);
if ((*Client)->cloaked)
free((*Client)->cloaked);
if ((*Client)->ipa_text)
free((*Client)->ipa_text);
free(*Client);
*Client = NULL;
}
static void static void
Generate_MyToken( CLIENT *Client ) Generate_MyToken( CLIENT *Client )
@@ -1451,7 +1317,7 @@ Generate_MyToken( CLIENT *Client )
{ {
if( c->mytoken == token ) if( c->mytoken == token )
{ {
/* The token is already in use */ /* Das Token wurde bereits vergeben */
token++; token++;
c = My_Clients; c = My_Clients;
continue; continue;
@@ -1558,7 +1424,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
if(Client->conn_id != NONE) { if(Client->conn_id != NONE) {
/* Local (directly connected) client */ /* Local (directly connected) client */
Log(LOG_NOTICE, Log(LOG_NOTICE,
"%s \"%s\" unregistered (connection %d): %s.", "%s \"%s\" unregistered (connection %d): %s",
Client_TypeText(Client), Client_Mask(Client), Client_TypeText(Client), Client_Mask(Client),
Client->conn_id, Txt); Client->conn_id, Txt);
Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]", Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]",
@@ -1576,7 +1442,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
} }
} else { } else {
/* Remote client */ /* Remote client */
LogDebug("%s \"%s\" unregistered: %s.", LogDebug("%s \"%s\" unregistered: %s",
Client_TypeText(Client), Client_Mask(Client), Txt); Client_TypeText(Client), Client_Mask(Client), Txt);
if(SendQuit) { if(SendQuit) {
@@ -1602,6 +1468,9 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
/** /**
* Introduce a new user or service client to a remote server. * Introduce a new user or service client to a remote server.
* *
* This function differentiates between RFC1459 and RFC2813 server links and
* generates the appropriate commands to register the new user or service.
*
* @param To The remote server to inform. * @param To The remote server to inform.
* @param Prefix Prefix for the generated commands. * @param Prefix Prefix for the generated commands.
* @param data CLIENT structure of the new client. * @param data CLIENT structure of the new client.
@@ -1610,100 +1479,43 @@ static void
cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data) cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data)
{ {
CLIENT *c = (CLIENT *)data; CLIENT *c = (CLIENT *)data;
(void)Client_Announce(To, Prefix, c);
} /* cb_introduceClient */
/**
* Announce an user or service to a server.
*
* This function differentiates between RFC1459 and RFC2813 server links and
* generates the appropriate commands to register the user or service.
*
* @param Client Server
* @param Prefix Prefix for the generated commands
* @param User User to announce
*/
GLOBAL bool
Client_Announce(CLIENT * Client, CLIENT * Prefix, CLIENT * User)
{
CONN_ID conn; CONN_ID conn;
char *modes, *user, *host; char *modes, *user, *host;
modes = Client_Modes(User); modes = Client_Modes(c);
user = Client_User(User) ? Client_User(User) : "-"; user = Client_User(c) ? Client_User(c) : "-";
host = Client_Hostname(User) ? Client_Hostname(User) : "-"; host = Client_Hostname(c) ? Client_Hostname(c) : "-";
conn = Client_Conn(Client); conn = Client_Conn(To);
if (Conn_Options(conn) & CONN_RFC1459) { if (Conn_Options(conn) & CONN_RFC1459) {
/* RFC 1459 mode: separate NICK and USER commands */ /* RFC 1459 mode: separate NICK and USER commands */
if (! Conn_WriteStr(conn, "NICK %s :%d", Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c),
Client_ID(User), Client_Hops(User) + 1)) Client_Hops(c) + 1);
return DISCONNECTED; Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
if (! Conn_WriteStr(conn, ":%s USER %s %s %s :%s", Client_ID(c), user, host,
Client_ID(User), user, host, Client_ID(Client_Introducer(c)), Client_Info(c));
Client_ID(Client_Introducer(User)), if (modes[0])
Client_Info(User))) Conn_WriteStr(conn, ":%s MODE %s +%s",
return DISCONNECTED; Client_ID(c), Client_ID(c), modes);
if (modes[0]) {
if (! Conn_WriteStr(conn, ":%s MODE %s +%s",
Client_ID(User), Client_ID(User),
modes))
return DISCONNECTED;
}
} else { } else {
/* RFC 2813 mode: one combined NICK or SERVICE command */ /* RFC 2813 mode: one combined NICK or SERVICE command */
if (Client_Type(User) == CLIENT_SERVICE if (Client_Type(c) == CLIENT_SERVICE
&& Client_HasFlag(Client, 'S')) { && strchr(Client_Flags(To), 'S'))
if (!IRC_WriteStrClientPrefix(Client, Prefix, IRC_WriteStrClientPrefix(To, Prefix,
"SERVICE %s %d * +%s %d :%s", "SERVICE %s %d * +%s %d :%s",
Client_Mask(User), Client_Mask(c),
Client_MyToken(Client_Introducer(User)), Client_MyToken(Client_Introducer(c)),
modes, Client_Hops(User) + 1, Client_Modes(c), Client_Hops(c) + 1,
Client_Info(User))) Client_Info(c));
return DISCONNECTED; else
} else { IRC_WriteStrClientPrefix(To, Prefix,
if (!IRC_WriteStrClientPrefix(Client, Prefix, "NICK %s %d %s %s %d +%s :%s",
"NICK %s %d %s %s %d +%s :%s", Client_ID(c), Client_Hops(c) + 1,
Client_ID(User), Client_Hops(User) + 1, user, host,
user, host, Client_MyToken(Client_Introducer(c)),
Client_MyToken(Client_Introducer(User)), modes, Client_Info(c));
modes, Client_Info(User)))
return DISCONNECTED;
}
} }
} /* cb_introduceClient */
if (Client_HasFlag(Client, 'M')) {
/* Synchronize metadata */
if (Client_HostnameCloaked(User)) {
if (!IRC_WriteStrClientPrefix(Client, Prefix,
"METADATA %s cloakhost :%s",
Client_ID(User),
Client_HostnameCloaked(User)))
return DISCONNECTED;
}
if (Client_AccountName(User)) {
if (!IRC_WriteStrClientPrefix(Client, Prefix,
"METADATA %s accountname :%s",
Client_ID(User),
Client_AccountName(User)))
return DISCONNECTED;
}
if (Conn_GetCertFp(Client_Conn(User))) {
if (!IRC_WriteStrClientPrefix(Client, Prefix,
"METADATA %s certfp :%s",
Client_ID(User),
Conn_GetCertFp(Client_Conn(User))))
return DISCONNECTED;
}
}
return CONNECTED;
} /* Client_Announce */
#ifdef DEBUG #ifdef DEBUG

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -17,20 +17,19 @@
* Client management (header) * Client management (header)
*/ */
#define CLIENT_UNKNOWN 0x0001 /* connection of unknown type */ #define CLIENT_UNKNOWN 1 /* connection of unknown type */
#define CLIENT_GOTPASS 0x0002 /* client did send PASS */ #define CLIENT_GOTPASS 2 /* client did send PASS */
#define CLIENT_GOTNICK 0x0004 /* client did send NICK */ #define CLIENT_GOTNICK 4 /* client did send NICK */
#define CLIENT_GOTUSER 0x0008 /* client did send USER */ #define CLIENT_GOTUSER 8 /* client did send USER */
#define CLIENT_USER 0x0010 /* client is an IRC user */ #define CLIENT_USER 16 /* client is an IRC user */
#define CLIENT_SERVER 0x0020 /* client is a server */ #define CLIENT_SERVER 32 /* client is a server */
#define CLIENT_SERVICE 0x0040 /* client is a service */ #define CLIENT_SERVICE 64 /* client is a service */
#define CLIENT_UNKNOWNSERVER 0x0080 /* unregistered server connection */ #define CLIENT_UNKNOWNSERVER 128 /* unregistered server connection */
#define CLIENT_GOTPASS_2813 0x0100 /* client did send PASS, RFC 2813 style */ #define CLIENT_GOTPASS_2813 256 /* client did send PASS, RFC 2813 style */
#ifndef STRICT_RFC #ifndef STRICT_RFC
# define CLIENT_WAITAUTHPING 0x0200 /* waiting for AUTH PONG from client */ # define CLIENT_WAITAUTHPING 512 /* waiting for AUTH PONG from client */
#endif #endif
#define CLIENT_WAITCAPEND 0x0400 /* waiting for "CAP END" command */ #define CLIENT_WAITCAPEND 1024 /* waiting for "CAP END" command */
#define CLIENT_ANY 0xFFFF
#define CLIENT_TYPE int #define CLIENT_TYPE int
@@ -49,8 +48,7 @@ typedef struct _CLIENT
struct _CLIENT *introducer; /* ID of the servers which the client is connected to */ struct _CLIENT *introducer; /* ID of the servers which the client is connected to */
struct _CLIENT *topserver; /* toplevel servers (only valid if client is a server) */ struct _CLIENT *topserver; /* toplevel servers (only valid if client is a server) */
char host[CLIENT_HOST_LEN]; /* hostname of the client */ char host[CLIENT_HOST_LEN]; /* hostname of the client */
char *cloaked; /* cloaked hostname of the client */ char cloaked[CLIENT_HOST_LEN]; /* cloaked hostname of the client */
char *ipa_text; /* textual representaton of IP address */
char user[CLIENT_USER_LEN]; /* user name ("login") */ char user[CLIENT_USER_LEN]; /* user name ("login") */
#if defined(PAM) && defined(IDENTAUTH) #if defined(PAM) && defined(IDENTAUTH)
char orig_user[CLIENT_USER_LEN];/* user name supplied by USER command */ char orig_user[CLIENT_USER_LEN];/* user name supplied by USER command */
@@ -58,9 +56,9 @@ typedef struct _CLIENT
char info[CLIENT_INFO_LEN]; /* long user name (user) / info text (server) */ char info[CLIENT_INFO_LEN]; /* long user name (user) / info text (server) */
char modes[CLIENT_MODE_LEN]; /* client modes */ char modes[CLIENT_MODE_LEN]; /* client modes */
int hops, token, mytoken; /* "hops" and "Token" (see SERVER command) */ int hops, token, mytoken; /* "hops" and "Token" (see SERVER command) */
char *away; /* AWAY text (valid if mode 'a' is set) */ bool oper_by_me; /* client is local IRC operator on this server? */
char away[CLIENT_AWAY_LEN]; /* AWAY text (valid if mode 'a' is set) */
char flags[CLIENT_FLAGS_LEN]; /* flags of the client */ char flags[CLIENT_FLAGS_LEN]; /* flags of the client */
char *account_name; /* login account (for services) */
int capabilities; /* enabled IRC capabilities */ int capabilities; /* enabled IRC capabilities */
} CLIENT; } CLIENT;
@@ -95,10 +93,7 @@ GLOBAL CLIENT *Client_ThisServer PARAMS(( void ));
GLOBAL CLIENT *Client_GetFromToken PARAMS(( CLIENT *Client, int Token )); GLOBAL CLIENT *Client_GetFromToken PARAMS(( CLIENT *Client, int Token ));
GLOBAL bool Client_Announce PARAMS(( CLIENT *Client, CLIENT *Prefix, CLIENT *User ));
GLOBAL CLIENT *Client_Search PARAMS(( const char *ID )); GLOBAL CLIENT *Client_Search PARAMS(( const char *ID ));
GLOBAL CLIENT *Client_SearchServer PARAMS(( const char *ID ));
GLOBAL CLIENT *Client_First PARAMS(( void )); GLOBAL CLIENT *Client_First PARAMS(( void ));
GLOBAL CLIENT *Client_Next PARAMS(( CLIENT *c )); GLOBAL CLIENT *Client_Next PARAMS(( CLIENT *c ));
@@ -115,24 +110,21 @@ GLOBAL char *Client_OrigUser PARAMS(( CLIENT *Client ));
GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client )); GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client ));
GLOBAL char *Client_HostnameCloaked PARAMS((CLIENT *Client)); GLOBAL char *Client_HostnameCloaked PARAMS((CLIENT *Client));
GLOBAL char *Client_HostnameDisplayed PARAMS(( CLIENT *Client )); GLOBAL char *Client_HostnameDisplayed PARAMS(( CLIENT *Client ));
GLOBAL const char *Client_IPAText PARAMS(( CLIENT *Client ));
GLOBAL char *Client_Modes PARAMS(( CLIENT *Client )); GLOBAL char *Client_Modes PARAMS(( CLIENT *Client ));
GLOBAL char *Client_Flags PARAMS(( CLIENT *Client )); GLOBAL char *Client_Flags PARAMS(( CLIENT *Client ));
GLOBAL CLIENT *Client_Introducer PARAMS(( CLIENT *Client )); GLOBAL CLIENT *Client_Introducer PARAMS(( CLIENT *Client ));
GLOBAL bool Client_OperByMe PARAMS(( CLIENT *Client ));
GLOBAL int Client_Hops PARAMS(( CLIENT *Client )); GLOBAL int Client_Hops PARAMS(( CLIENT *Client ));
GLOBAL int Client_Token PARAMS(( CLIENT *Client )); GLOBAL int Client_Token PARAMS(( CLIENT *Client ));
GLOBAL int Client_MyToken PARAMS(( CLIENT *Client )); GLOBAL int Client_MyToken PARAMS(( CLIENT *Client ));
GLOBAL CLIENT *Client_TopServer PARAMS(( CLIENT *Client )); GLOBAL CLIENT *Client_TopServer PARAMS(( CLIENT *Client ));
GLOBAL CLIENT *Client_NextHop PARAMS(( CLIENT *Client )); GLOBAL CLIENT *Client_NextHop PARAMS(( CLIENT *Client ));
GLOBAL char *Client_Away PARAMS(( CLIENT *Client )); GLOBAL char *Client_Away PARAMS(( CLIENT *Client ));
GLOBAL char *Client_AccountName PARAMS((CLIENT *Client));
GLOBAL time_t Client_StartTime PARAMS(( CLIENT *Client )); GLOBAL time_t Client_StartTime PARAMS(( CLIENT *Client ));
GLOBAL bool Client_HasMode PARAMS(( CLIENT *Client, char Mode )); GLOBAL bool Client_HasMode PARAMS(( CLIENT *Client, char Mode ));
GLOBAL bool Client_HasFlag PARAMS(( CLIENT *Client, char Flag ));
GLOBAL void Client_SetHostname PARAMS(( CLIENT *Client, const char *Hostname )); GLOBAL void Client_SetHostname PARAMS(( CLIENT *Client, const char *Hostname ));
GLOBAL void Client_SetIPAText PARAMS(( CLIENT *Client, const char *IPAText ));
GLOBAL void Client_SetID PARAMS(( CLIENT *Client, const char *Nick )); GLOBAL void Client_SetID PARAMS(( CLIENT *Client, const char *Nick ));
GLOBAL void Client_SetUser PARAMS(( CLIENT *Client, const char *User, bool Idented )); GLOBAL void Client_SetUser PARAMS(( CLIENT *Client, const char *User, bool Idented ));
GLOBAL void Client_SetOrigUser PARAMS(( CLIENT *Client, const char *User )); GLOBAL void Client_SetOrigUser PARAMS(( CLIENT *Client, const char *User ));
@@ -140,11 +132,11 @@ GLOBAL void Client_SetInfo PARAMS(( CLIENT *Client, const char *Info ));
GLOBAL void Client_SetType PARAMS(( CLIENT *Client, int Type )); GLOBAL void Client_SetType PARAMS(( CLIENT *Client, int Type ));
GLOBAL void Client_SetHops PARAMS(( CLIENT *Client, int Hops )); GLOBAL void Client_SetHops PARAMS(( CLIENT *Client, int Hops ));
GLOBAL void Client_SetToken PARAMS(( CLIENT *Client, int Token )); GLOBAL void Client_SetToken PARAMS(( CLIENT *Client, int Token ));
GLOBAL void Client_SetOperByMe PARAMS(( CLIENT *Client, bool OperByMe ));
GLOBAL void Client_SetModes PARAMS(( CLIENT *Client, const char *Modes )); GLOBAL void Client_SetModes PARAMS(( CLIENT *Client, const char *Modes ));
GLOBAL void Client_SetFlags PARAMS(( CLIENT *Client, const char *Flags )); GLOBAL void Client_SetFlags PARAMS(( CLIENT *Client, const char *Flags ));
GLOBAL void Client_SetIntroducer PARAMS(( CLIENT *Client, CLIENT *Introducer )); GLOBAL void Client_SetIntroducer PARAMS(( CLIENT *Client, CLIENT *Introducer ));
GLOBAL void Client_SetAway PARAMS(( CLIENT *Client, const char *Txt )); GLOBAL void Client_SetAway PARAMS(( CLIENT *Client, const char *Txt ));
GLOBAL void Client_SetAccountName PARAMS((CLIENT *Client, const char *AccountName));
GLOBAL bool Client_ModeAdd PARAMS(( CLIENT *Client, char Mode )); GLOBAL bool Client_ModeAdd PARAMS(( CLIENT *Client, char Mode ));
GLOBAL bool Client_ModeDel PARAMS(( CLIENT *Client, char Mode )); GLOBAL bool Client_ModeDel PARAMS(( CLIENT *Client, char Mode ));

View File

@@ -37,7 +37,6 @@ struct ConnSSL_State {
void *cookie; /* pointer to server configuration structure void *cookie; /* pointer to server configuration structure
(for outgoing connections), or NULL. */ (for outgoing connections), or NULL. */
#endif #endif
char *fingerprint;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -75,7 +75,6 @@ struct SSLOptions {
char *DHFile; /**< File containing DH parameters */ char *DHFile; /**< File containing DH parameters */
array ListenPorts; /**< Array of listening SSL ports */ array ListenPorts; /**< Array of listening SSL ports */
array KeyFilePassword; /**< Key file password */ array KeyFilePassword; /**< Key file password */
char *CipherList; /**< Set SSL cipher list to use */
}; };
#endif #endif
@@ -112,9 +111,6 @@ GLOBAL char Conf_ServerAdminMail[CLIENT_INFO_LEN];
/** Message of the day (MOTD) of this server */ /** Message of the day (MOTD) of this server */
GLOBAL array Conf_Motd; GLOBAL array Conf_Motd;
/** Help text of this server */
GLOBAL array Conf_Helptext;
/** Array of ports this server should listen on */ /** Array of ports this server should listen on */
GLOBAL array Conf_ListenPorts; GLOBAL array Conf_ListenPorts;
@@ -149,8 +145,8 @@ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS];
/** Array of pre-defined channels */ /** Array of pre-defined channels */
GLOBAL array Conf_Channels; GLOBAL array Conf_Channels;
/** String containing all locally allowed channel prefixes for new channels */ /** Flag indicating if only pre-defined channels are allowed (true) or not */
GLOBAL char Conf_AllowedChannelTypes[8]; GLOBAL bool Conf_PredefChannelsOnly;
/** Flag indicating if IRC operators are allowed to always use MODE (true) */ /** Flag indicating if IRC operators are allowed to always use MODE (true) */
GLOBAL bool Conf_OperCanMode; GLOBAL bool Conf_OperCanMode;
@@ -203,9 +199,6 @@ GLOBAL bool Conf_PAMIsOptional;
/** Disable all CTCP commands except for /me ? */ /** Disable all CTCP commands except for /me ? */
GLOBAL bool Conf_ScrubCTCP; GLOBAL bool Conf_ScrubCTCP;
/** Default user modes for new local clients */
GLOBAL char Conf_DefaultUserModes[CLIENT_MODE_LEN];
/* /*
* try to connect to remote systems using the ipv6 protocol, * try to connect to remote systems using the ipv6 protocol,
* if they have an ipv6 address? (default yes) * if they have an ipv6 address? (default yes)
@@ -215,9 +208,6 @@ GLOBAL bool Conf_ConnectIPv6;
/** Try to connect to remote systems using the IPv4 protocol (true) */ /** Try to connect to remote systems using the IPv4 protocol (true) */
GLOBAL bool Conf_ConnectIPv4; GLOBAL bool Conf_ConnectIPv4;
/** Idle timout (seconds), after which the daemon should exit */
GLOBAL int Conf_IdleTimeout;
/** Maximum number of simultaneous connections to this server */ /** Maximum number of simultaneous connections to this server */
GLOBAL int Conf_MaxConnections; GLOBAL int Conf_MaxConnections;

View File

@@ -123,7 +123,7 @@ Convert_Message(iconv_t Handle, char *Message)
out_left = sizeof(Encoding_Buffer) - 1; out_left = sizeof(Encoding_Buffer) - 1;
if (iconv(Handle, &Message, &in_left, &out, &out_left) == (size_t)(-1)) { if (iconv(Handle, &Message, &in_left, &out, &out_left) == (size_t)(-1)) {
/* An error occurred! */ /* An error occured! */
LogDebug("Error converting message encoding!"); LogDebug("Error converting message encoding!");
strlcpy(Encoding_Buffer, Message, sizeof(Encoding_Buffer)); strlcpy(Encoding_Buffer, Message, sizeof(Encoding_Buffer));
iconv(Handle, NULL, NULL, NULL, NULL); iconv(Handle, NULL, NULL, NULL, NULL);

View File

@@ -137,6 +137,8 @@ Conn_Flag( CONN_ID Idx )
GLOBAL void GLOBAL void
Conn_SetFlag( CONN_ID Idx, int Flag ) Conn_SetFlag( CONN_ID Idx, int Flag )
{ {
/* Connection markieren */
assert( Idx > NONE ); assert( Idx > NONE );
My_Connections[Idx].flag = Flag; My_Connections[Idx].flag = Flag;
} /* Conn_SetFlag */ } /* Conn_SetFlag */
@@ -145,6 +147,9 @@ Conn_SetFlag( CONN_ID Idx, int Flag )
GLOBAL CONN_ID GLOBAL CONN_ID
Conn_First( void ) Conn_First( void )
{ {
/* Connection-Struktur der ersten Verbindung liefern;
* Ist keine Verbindung vorhanden, wird NONE geliefert. */
CONN_ID i; CONN_ID i;
for( i = 0; i < Pool_Size; i++ ) for( i = 0; i < Pool_Size; i++ )
@@ -158,6 +163,9 @@ Conn_First( void )
GLOBAL CONN_ID GLOBAL CONN_ID
Conn_Next( CONN_ID Idx ) Conn_Next( CONN_ID Idx )
{ {
/* Naechste Verbindungs-Struktur liefern; existiert keine
* weitere, so wird NONE geliefert. */
CONN_ID i = NONE; CONN_ID i = NONE;
assert( Idx > NONE ); assert( Idx > NONE );

View File

@@ -54,16 +54,11 @@ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
#define DH_BITS 2048 #define DH_BITS 2048
#define DH_BITS_MIN 1024 #define DH_BITS_MIN 1024
#define MAX_HASH_SIZE 64 /* from gnutls-int.h */
static gnutls_certificate_credentials_t x509_cred; static gnutls_certificate_credentials_t x509_cred;
static gnutls_dh_params_t dh_params; static gnutls_dh_params_t dh_params;
static gnutls_priority_t priorities_cache;
static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void )); static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
#endif #endif
#define SHA256_STRING_LEN (32 * 2 + 1)
static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c )); static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
static int ConnectAccept PARAMS(( CONNECTION *c, bool connect )); static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname )); static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
@@ -114,26 +109,17 @@ out:
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
/**
* Log OpenSSL error message.
*
* @param msg The error message.
* @param info Additional information text or NULL.
*/
static void static void
LogOpenSSLError(const char *error, const char *info) LogOpenSSLError( const char *msg, const char *msg2 )
{ {
unsigned long err = ERR_get_error(); unsigned long err = ERR_get_error();
char * errmsg = err char * errmsg = err ? ERR_error_string(err, NULL) : "Unable to determine error";
? ERR_error_string(err, NULL)
: "Unable to determine error";
assert(error != NULL); if (!msg) msg = "SSL Error";
if (msg2)
if (info) Log( LOG_ERR, "%s: %s: %s", msg, msg2, errmsg);
Log(LOG_ERR, "%s: %s (%s)", error, info, errmsg);
else else
Log(LOG_ERR, "%s: %s", error, errmsg); Log( LOG_ERR, "%s: %s", msg, errmsg);
} }
@@ -152,20 +138,13 @@ pem_passwd_cb(char *buf, int size, int rwflag, void *password)
LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen); LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
assert(passlen >= 0); assert(passlen >= 0);
if (passlen <= 0) { if (passlen <= 0) {
Log(LOG_ERR, "PEM password required but not set [in pem_passwd_cb()]!"); Log(LOG_ERR, "pem_passwd_cb: password required, but not set");
return 0; return 0;
} }
size = passlen > size ? size : passlen; size = passlen > size ? size : passlen;
memcpy(buf, (char *)(array_start(pass)), size); memcpy(buf, (char *)(array_start(pass)), size);
return size; return size;
} }
static int
Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
{
return 1;
}
#endif #endif
@@ -187,7 +166,7 @@ Load_DH_params(void)
} }
dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL); dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
if (!dh_params) { if (!dh_params) {
Log(LOG_ERR, "%s: Failed to read SSL DH parameters!", Log(LOG_ERR, "%s: PEM_read_DHparams failed!",
Conf_SSLOptions.DHFile); Conf_SSLOptions.DHFile);
ret = false; ret = false;
} }
@@ -201,8 +180,7 @@ Load_DH_params(void)
err = gnutls_dh_params_init(&tmp_dh_params); err = gnutls_dh_params_init(&tmp_dh_params);
if (err < 0) { if (err < 0) {
Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s", Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
gnutls_strerror(err));
return false; return false;
} }
if (Conf_SSLOptions.DHFile) { if (Conf_SSLOptions.DHFile) {
@@ -215,9 +193,7 @@ Load_DH_params(void)
if (err == 0) if (err == 0)
need_dhgenerate = false; need_dhgenerate = false;
else else
Log(LOG_ERR, Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
"Failed to initialize SSL DH parameters: %s",
gnutls_strerror(err));
memset(dhparms.data, 0, size); memset(dhparms.data, 0, size);
free(dhparms.data); free(dhparms.data);
@@ -229,8 +205,7 @@ Load_DH_params(void)
DH_BITS); DH_BITS);
err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS); err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
if (err < 0) { if (err < 0) {
Log(LOG_ERR, "Failed to generate SSL DH parameters: %s", Log(LOG_ERR, "gnutls_dh_params_generate2: %s", gnutls_strerror(err));
gnutls_strerror(err));
return false; return false;
} }
} }
@@ -248,10 +223,6 @@ void ConnSSL_Free(CONNECTION *c)
SSL_shutdown(ssl); SSL_shutdown(ssl);
SSL_free(ssl); SSL_free(ssl);
c->ssl_state.ssl = NULL; c->ssl_state.ssl = NULL;
if (c->ssl_state.fingerprint) {
free(c->ssl_state.fingerprint);
c->ssl_state.fingerprint = NULL;
}
} }
#endif #endif
#ifdef HAVE_LIBGNUTLS #ifdef HAVE_LIBGNUTLS
@@ -286,10 +257,8 @@ ConnSSL_InitLibrary( void )
if (!RAND_status()) { if (!RAND_status()) {
Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?"); Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
/* /*
* it is probably best to fail and let the user install EGD or * it is probably best to fail and let the user install EGD or a similar program if no kernel random device is available.
* a similar program if no kernel random device is available. * According to OpenSSL RAND_egd(3): "The automatic query of /var/run/egd-pool et al was added in OpenSSL 0.9.7";
* According to OpenSSL RAND_egd(3): "The automatic query of
* /var/run/egd-pool et al was added in OpenSSL 0.9.7";
* so it makes little sense to deal with PRNGD seeding ourselves. * so it makes little sense to deal with PRNGD seeding ourselves.
*/ */
array_free(&Conf_SSLOptions.ListenPorts); array_free(&Conf_SSLOptions.ListenPorts);
@@ -298,7 +267,7 @@ ConnSSL_InitLibrary( void )
newctx = SSL_CTX_new(SSLv23_method()); newctx = SSL_CTX_new(SSLv23_method());
if (!newctx) { if (!newctx) {
LogOpenSSLError("Failed to create SSL context", NULL); LogOpenSSLError("SSL_CTX_new()", NULL);
array_free(&Conf_SSLOptions.ListenPorts); array_free(&Conf_SSLOptions.ListenPorts);
return false; return false;
} }
@@ -306,16 +275,8 @@ ConnSSL_InitLibrary( void )
if (!ConnSSL_LoadServerKey_openssl(newctx)) if (!ConnSSL_LoadServerKey_openssl(newctx))
goto out; goto out;
if (SSL_CTX_set_cipher_list(newctx, Conf_SSLOptions.CipherList) == 0) {
Log(LOG_ERR, "Failed to apply OpenSSL cipher list \"%s\"!",
Conf_SSLOptions.CipherList);
goto out;
}
SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2); SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
Verify_openssl);
SSL_CTX_free(ssl_ctx); SSL_CTX_free(ssl_ctx);
ssl_ctx = newctx; ssl_ctx = newctx;
Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION)); Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
@@ -328,37 +289,22 @@ out:
#ifdef HAVE_LIBGNUTLS #ifdef HAVE_LIBGNUTLS
int err; int err;
static bool initialized; static bool initialized;
if (initialized) /* TODO: cannot reload gnutls keys: can't simply free x509 context -- it may still be in use */
if (initialized) {
/* TODO: cannot reload gnutls keys: can't simply free x509
* context -- it may still be in use */
return false; return false;
}
err = gnutls_global_init(); err = gnutls_global_init();
if (err) { if (err) {
Log(LOG_ERR, "Failed to initialize GnuTLS: %s", Log(LOG_ERR, "gnutls_global_init(): %s", gnutls_strerror(err));
gnutls_strerror(err)); array_free(&Conf_SSLOptions.ListenPorts);
goto out; return false;
} }
if (!ConnSSL_LoadServerKey_gnutls()) {
if (!ConnSSL_LoadServerKey_gnutls()) array_free(&Conf_SSLOptions.ListenPorts);
goto out; return false;
if (gnutls_priority_init(&priorities_cache, Conf_SSLOptions.CipherList,
NULL) != GNUTLS_E_SUCCESS) {
Log(LOG_ERR,
"Failed to apply GnuTLS cipher list \"%s\"!",
Conf_SSLOptions.CipherList);
goto out;
} }
Log(LOG_INFO, "gnutls %s initialized.", gnutls_check_version(NULL));
Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
initialized = true; initialized = true;
return true; return true;
out:
array_free(&Conf_SSLOptions.ListenPorts);
return false;
#endif #endif
} }
@@ -372,8 +318,7 @@ ConnSSL_LoadServerKey_gnutls(void)
err = gnutls_certificate_allocate_credentials(&x509_cred); err = gnutls_certificate_allocate_credentials(&x509_cred);
if (err < 0) { if (err < 0) {
Log(LOG_ERR, "Failed to allocate certificate credentials: %s", Log(LOG_ERR, "gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
gnutls_strerror(err));
return false; return false;
} }
@@ -385,7 +330,7 @@ ConnSSL_LoadServerKey_gnutls(void)
if (array_bytes(&Conf_SSLOptions.KeyFilePassword)) if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
Log(LOG_WARNING, Log(LOG_WARNING,
"Ignoring SSL \"KeyFilePassword\": Not supported by GnuTLS."); "Ignoring KeyFilePassword: Not supported by GNUTLS.");
if (!Load_DH_params()) if (!Load_DH_params())
return false; return false;
@@ -393,11 +338,8 @@ ConnSSL_LoadServerKey_gnutls(void)
gnutls_certificate_set_dh_params(x509_cred, dh_params); gnutls_certificate_set_dh_params(x509_cred, dh_params);
err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM); err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
if (err < 0) { if (err < 0) {
Log(LOG_ERR, Log(LOG_ERR, "gnutls_certificate_set_x509_key_file (cert %s, key %s): %s",
"Failed to set certificate key file (cert %s, key %s): %s", cert_file, Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)", gnutls_strerror(err));
cert_file,
Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)",
gnutls_strerror(err));
return false; return false;
} }
return true; return true;
@@ -422,26 +364,26 @@ ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) { if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
array_free_wipe(&Conf_SSLOptions.KeyFilePassword); array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
LogOpenSSLError("Failed to add private key", Conf_SSLOptions.KeyFile); LogOpenSSLError("SSL_CTX_use_PrivateKey_file", Conf_SSLOptions.KeyFile);
return false; return false;
} }
cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile; cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) { if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
array_free_wipe(&Conf_SSLOptions.KeyFilePassword); array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
LogOpenSSLError("Failed to load certificate chain", cert_key); LogOpenSSLError("SSL_CTX_use_certificate_file", cert_key);
return false; return false;
} }
array_free_wipe(&Conf_SSLOptions.KeyFilePassword); array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
if (!SSL_CTX_check_private_key(ctx)) { if (!SSL_CTX_check_private_key(ctx)) {
LogOpenSSLError("Server private key does not match certificate", NULL); LogOpenSSLError("Server Private Key does not match certificate", NULL);
return false; return false;
} }
if (Load_DH_params()) { if (Load_DH_params()) {
if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1) if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1)
LogOpenSSLError("Error setting DH parameters", Conf_SSLOptions.DHFile); LogOpenSSLError("Error setting DH Parameters", Conf_SSLOptions.DHFile);
/* don't return false here: the non-DH modes will still work */ /* don't return false here: the non-DH modes will still work */
DH_free(dh_params); DH_free(dh_params);
dh_params = NULL; dh_params = NULL;
@@ -455,39 +397,31 @@ static bool
ConnSSL_Init_SSL(CONNECTION *c) ConnSSL_Init_SSL(CONNECTION *c)
{ {
int ret; int ret;
LogDebug("Initializing SSL ...");
assert(c != NULL); assert(c != NULL);
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
if (!ssl_ctx) { if (!ssl_ctx) {
Log(LOG_ERR, Log(LOG_ERR, "Cannot init ssl_ctx: OpenSSL initialization failed at startup");
"Can't initialize SSL context, OpenSSL initialization failed at startup!");
return false; return false;
} }
assert(c->ssl_state.ssl == NULL); assert(c->ssl_state.ssl == NULL);
assert(c->ssl_state.fingerprint == NULL);
c->ssl_state.ssl = SSL_new(ssl_ctx); c->ssl_state.ssl = SSL_new(ssl_ctx);
if (!c->ssl_state.ssl) { if (!c->ssl_state.ssl) {
LogOpenSSLError("Failed to create SSL structure", NULL); LogOpenSSLError("SSL_new()", NULL);
return false; return false;
} }
Conn_OPTION_ADD(c, CONN_SSL);
ret = SSL_set_fd(c->ssl_state.ssl, c->sock); ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
if (ret != 1) { if (ret != 1) {
LogOpenSSLError("Failed to set SSL file descriptor", NULL); LogOpenSSLError("SSL_set_fd()", NULL);
ConnSSL_Free(c); ConnSSL_Free(c);
return false; return false;
} }
#endif #endif
#ifdef HAVE_LIBGNUTLS #ifdef HAVE_LIBGNUTLS
Conn_OPTION_ADD(c, CONN_SSL); ret = gnutls_set_default_priority(c->ssl_state.gnutls_session);
ret = gnutls_priority_set(c->ssl_state.gnutls_session, priorities_cache); if (ret < 0) {
if (ret != GNUTLS_E_SUCCESS) { Log(LOG_ERR, "gnutls_set_default_priority: %s", gnutls_strerror(ret));
Log(LOG_ERR, "Failed to set GnuTLS session priorities: %s",
gnutls_strerror(ret));
ConnSSL_Free(c); ConnSSL_Free(c);
return false; return false;
} }
@@ -497,20 +431,16 @@ ConnSSL_Init_SSL(CONNECTION *c)
* There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g. * There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g.
* http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html * http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
*/ */
gnutls_transport_set_ptr(c->ssl_state.gnutls_session, gnutls_transport_set_ptr(c->ssl_state.gnutls_session, (gnutls_transport_ptr_t) (long) c->sock);
(gnutls_transport_ptr_t) (long) c->sock); ret = gnutls_credentials_set(c->ssl_state.gnutls_session, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_certificate_server_set_request(c->ssl_state.gnutls_session, if (ret < 0) {
GNUTLS_CERT_REQUEST); Log(LOG_ERR, "gnutls_credentials_set: %s", gnutls_strerror(ret));
ret = gnutls_credentials_set(c->ssl_state.gnutls_session,
GNUTLS_CRD_CERTIFICATE, x509_cred);
if (ret != 0) {
Log(LOG_ERR, "Failed to set SSL credentials: %s",
gnutls_strerror(ret));
ConnSSL_Free(c); ConnSSL_Free(c);
return false; return false;
} }
gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN); gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
#endif #endif
Conn_OPTION_ADD(c, CONN_SSL);
return true; return true;
} }
@@ -524,8 +454,7 @@ ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT); err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
if (err) { if (err) {
Log(LOG_ERR, "Failed to initialize new SSL session: %s", Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
gnutls_strerror(err));
return false; return false;
} }
#endif #endif
@@ -541,23 +470,16 @@ ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
} }
/** /*
* Check and handle error return codes after failed calls to SSL functions. Check an Handle Error return code after failed calls to ssl/tls functions.
* OpenSSL:
* OpenSSL: SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl.
* SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or GNUTLS:
* SSL_write() on ssl. gnutlsssl_read(), gnutls_write() or gnutls_handshake().
* Return: -1 on fatal error, 0 if we can try again later.
* GnuTLS:
* gnutlsssl_read(), gnutls_write() or gnutls_handshake().
*
* @param c The connection handle.
* @prarm code The return code.
* @param fname The name of the function in which the error occurred.
* @return -1 on fatal errors, 0 if we can try again later.
*/ */
static int static int
ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname) ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
{ {
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
int ret = SSL_ERROR_SYSCALL; int ret = SSL_ERROR_SYSCALL;
@@ -565,7 +487,6 @@ ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
int real_errno = errno; int real_errno = errno;
ret = SSL_get_error(c->ssl_state.ssl, code); ret = SSL_get_error(c->ssl_state.ssl, code);
switch (ret) { switch (ret) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
io_event_del(c->sock, IO_WANTWRITE); io_event_del(c->sock, IO_WANTWRITE);
@@ -577,33 +498,31 @@ ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
return 0; /* try again later */ return 0; /* try again later */
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
LogDebug("SSL connection shut down normally."); LogDebug("TLS/SSL connection shut down normally");
break; break;
/*
SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT, SSL_ERROR_WANT_X509_LOOKUP
*/
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
/* SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
* and SSL_ERROR_WANT_X509_LOOKUP */
sslerr = ERR_get_error(); sslerr = ERR_get_error();
if (sslerr) { if (sslerr) {
Log(LOG_ERR, "SSL error: %s [in %s()]!", Log( LOG_ERR, "%s: %s", fname, ERR_error_string(sslerr, NULL ));
ERR_error_string(sslerr, NULL), fname);
} else { } else {
switch (code) { /* EOF that violated protocol */ switch (code) { /* EOF that violated protocol */
case 0: case 0:
Log(LOG_ERR, Log(LOG_ERR, "%s: Client Disconnected", fname );
"SSL error, client disconnected [in %s()]!",
fname);
break; break;
case -1: /* low level socket I/O error, check errno */ case -1: /* low level socket I/O error, check errno */
Log(LOG_ERR, "SSL error: %s [in %s()]!", Log(LOG_ERR, "%s: %s", fname, strerror(real_errno));
strerror(real_errno), fname);
} }
} }
break; break;
case SSL_ERROR_SSL: case SSL_ERROR_SSL:
LogOpenSSLError("SSL protocol error", fname); LogOpenSSLError("TLS/SSL Protocol Error", fname);
break; break;
default: default:
Log(LOG_ERR, "Unknown SSL error %d [in %s()]!", ret, fname); Log( LOG_ERR, "%s: Unknown error %d!", fname, ret);
} }
ConnSSL_Free(c); ConnSSL_Free(c);
return -1; return -1;
@@ -623,8 +542,7 @@ ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
default: default:
assert(code < 0); assert(code < 0);
if (gnutls_error_is_fatal(code)) { if (gnutls_error_is_fatal(code)) {
Log(LOG_ERR, "SSL error: %s [%s].", Log(LOG_ERR, "%s: %s", fname, gnutls_strerror(code));
gnutls_strerror(code), fname);
ConnSSL_Free(c); ConnSSL_Free(c);
return -1; return -1;
} }
@@ -673,11 +591,11 @@ ConnSSL_Accept( CONNECTION *c )
#ifdef HAVE_LIBGNUTLS #ifdef HAVE_LIBGNUTLS
int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER); int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
if (err) { if (err) {
Log(LOG_ERR, "Failed to initialize new SSL session: %s", Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
gnutls_strerror(err));
return false; return false;
} }
#endif #endif
LogDebug("ConnSSL_Accept: Initializing SSL data");
if (!ConnSSL_Init_SSL(c)) if (!ConnSSL_Init_SSL(c))
return -1; return -1;
} }
@@ -696,80 +614,6 @@ ConnSSL_Connect( CONNECTION *c )
return ConnectAccept(c, true); return ConnectAccept(c, true);
} }
static int
ConnSSL_InitCertFp( CONNECTION *c )
{
const char hex[] = "0123456789abcdef";
int i;
#ifdef HAVE_LIBSSL
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_size;
X509 *cert;
cert = SSL_get_peer_certificate(c->ssl_state.ssl);
if (!cert)
return 0;
if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) {
X509_free(cert);
return 0;
}
X509_free(cert);
#endif /* HAVE_LIBSSL */
#ifdef HAVE_LIBGNUTLS
gnutls_x509_crt_t cert;
unsigned int cert_list_size;
const gnutls_datum_t *cert_list;
unsigned char digest[MAX_HASH_SIZE];
size_t digest_size;
if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) !=
GNUTLS_CRT_X509)
return 0;
if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
return 0;
cert_list_size = 0;
cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
&cert_list_size);
if (!cert_list) {
gnutls_x509_crt_deinit(cert);
return 0;
}
if (gnutls_x509_crt_import(cert, &cert_list[0],
GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
gnutls_x509_crt_deinit(cert);
return 0;
}
digest_size = sizeof(digest);
if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest,
&digest_size)) {
gnutls_x509_crt_deinit(cert);
return 0;
}
gnutls_x509_crt_deinit(cert);
#endif /* HAVE_LIBGNUTLS */
assert(c->ssl_state.fingerprint == NULL);
c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN);
if (!c->ssl_state.fingerprint)
return 0;
for (i = 0; i < (int)digest_size; i++) {
c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
}
c->ssl_state.fingerprint[i * 2] = '\0';
return 1;
}
/* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */ /* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
static int static int
@@ -790,8 +634,6 @@ ConnectAccept( CONNECTION *c, bool connect)
if (ret) if (ret)
return ConnSSL_HandleError(c, ret, "gnutls_handshake"); return ConnSSL_HandleError(c, ret, "gnutls_handshake");
#endif /* _GNUTLS */ #endif /* _GNUTLS */
(void)ConnSSL_InitCertFp(c);
Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT)); Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
ConnSSL_LogCertInfo(c); ConnSSL_LogCertInfo(c);
@@ -883,19 +725,6 @@ ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
#endif #endif
} }
char *
ConnSSL_GetCertFp(CONNECTION *c)
{
return c->ssl_state.fingerprint;
}
bool
ConnSSL_SetCertFp(CONNECTION *c, const char *fingerprint)
{
assert (c != NULL);
c->ssl_state.fingerprint = strndup(fingerprint, SHA256_STRING_LEN - 1);
return c->ssl_state.fingerprint != NULL;
}
#else #else
bool bool

View File

@@ -26,9 +26,6 @@ GLOBAL ssize_t ConnSSL_Write PARAMS(( CONNECTION *c, const void *buf, size_t cou
GLOBAL ssize_t ConnSSL_Read PARAMS(( CONNECTION *c, void *buf, size_t count)); GLOBAL ssize_t ConnSSL_Read PARAMS(( CONNECTION *c, void *buf, size_t count));
GLOBAL bool ConnSSL_GetCipherInfo PARAMS(( CONNECTION *c, char *buf, size_t len )); GLOBAL bool ConnSSL_GetCipherInfo PARAMS(( CONNECTION *c, char *buf, size_t len ));
GLOBAL char *ConnSSL_GetCertFp PARAMS(( CONNECTION *c ));
GLOBAL bool ConnSSL_SetCertFp PARAMS(( CONNECTION *c, const char *fingerprint ));
#endif /* SSL_SUPPORT */ #endif /* SSL_SUPPORT */
#endif /* conn_ssl_h */ #endif /* conn_ssl_h */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -82,8 +82,6 @@
#define MAX_COMMANDS_SERVER_MIN 10 #define MAX_COMMANDS_SERVER_MIN 10
#define MAX_COMMANDS_SERVICE 10 #define MAX_COMMANDS_SERVICE 10
#define SD_LISTEN_FDS_START 3
static bool Handle_Write PARAMS(( CONN_ID Idx )); static bool Handle_Write PARAMS(( CONN_ID Idx ));
static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len )); static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
@@ -121,42 +119,6 @@ static void cb_Read_Resolver_Result PARAMS((int sock, UNUSED short what));
static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what)); static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what));
static void cb_clientserver PARAMS((int sock, short what)); static void cb_clientserver PARAMS((int sock, short what));
time_t idle_t = 0;
/**
* Get number of sockets available from systemd(8).
*
* ngIRCd needs to implement its own sd_listen_fds(3) function and can't
* use the one provided by systemd itself, because the sockets will be
* used in a forked child process with a new PID, and this would trigger
* an error in the standard implementation.
*
* @return Number of sockets available, -1 if sockets have already been
* initialized, or 0 when no sockets have been passed.
*/
static int
my_sd_listen_fds(void)
{
const char *e;
int count;
/* Check if LISTEN_PID exists; but we ignore the result, because
* normally ngircd forks a child before checking this, and therefore
* the PID set in the environment is always wrong ... */
e = getenv("LISTEN_PID");
if (!e || !*e)
return 0;
e = getenv("LISTEN_FDS");
if (!e || !*e)
return -1;
count = atoi(e);
unsetenv("LISTEN_FDS");
return count;
}
/** /**
* IO callback for listening sockets: handle new connections. This callback * IO callback for listening sockets: handle new connections. This callback
@@ -222,7 +184,7 @@ cb_connserver(int sock, UNUSED short what)
if (server < 0) { if (server < 0) {
Log(LOG_ERR, "Connection on socket %d to \"%s\" aborted!", Log(LOG_ERR, "Connection on socket %d to \"%s\" aborted!",
sock, My_Connections[idx].host); sock, My_Connections[idx].host);
Conn_Close(idx, "Connection aborted", NULL, false); Conn_Close(idx, "Connection aborted!", NULL, false);
return; return;
} }
@@ -243,7 +205,7 @@ cb_connserver(int sock, UNUSED short what)
My_Connections[idx].host, Conf_Server[server].port, My_Connections[idx].host, Conf_Server[server].port,
idx, strerror(err)); idx, strerror(err));
Conn_Close(idx, "Can't connect", NULL, false); Conn_Close(idx, "Can't connect!", NULL, false);
if (ng_ipaddr_af(&Conf_Server[server].dst_addr[0])) { if (ng_ipaddr_af(&Conf_Server[server].dst_addr[0])) {
/* more addresses to try... */ /* more addresses to try... */
@@ -320,7 +282,7 @@ cb_connserver_login_ssl(int sock, short unused)
return; return;
case -1: case -1:
Log(LOG_ERR, "SSL connection on socket %d failed!", sock); Log(LOG_ERR, "SSL connection on socket %d failed!", sock);
Conn_Close(idx, "Can't connect", NULL, false); Conn_Close(idx, "Can't connect!", NULL, false);
return; return;
} }
@@ -367,13 +329,13 @@ cb_clientserver(int sock, short what)
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
/** /**
* IO callback for new SSL-enabled client and server connections. * IO callback for established SSL-enabled client and server connections.
* *
* @param sock Socket descriptor. * @param sock Socket descriptor.
* @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...). * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...).
*/ */
static void static void
cb_clientserver_ssl(int sock, UNUSED short what) cb_clientserver_ssl(int sock, short what)
{ {
CONN_ID idx = Socket2Index(sock); CONN_ID idx = Socket2Index(sock);
@@ -390,11 +352,14 @@ cb_clientserver_ssl(int sock, UNUSED short what)
case 0: case 0:
return; /* EAGAIN: callback will be invoked again by IO layer */ return; /* EAGAIN: callback will be invoked again by IO layer */
default: default:
Conn_Close(idx, Conn_Close(idx, "SSL accept error, closing socket", "SSL accept error", false);
"SSL accept error, closing socket", "SSL accept error",
false);
return; return;
} }
if (what & IO_WANTREAD)
Read_Request(idx);
if (what & IO_WANTWRITE)
Handle_Write(idx);
io_event_setcb(sock, cb_clientserver); /* SSL handshake completed */ io_event_setcb(sock, cb_clientserver); /* SSL handshake completed */
} }
@@ -402,13 +367,14 @@ cb_clientserver_ssl(int sock, UNUSED short what)
/** /**
* Initialize connection module. * Initialize connecion module.
*/ */
GLOBAL void GLOBAL void
Conn_Init( void ) Conn_Init( void )
{ {
CONN_ID i; CONN_ID i;
/* Speicher fuer Verbindungs-Pool anfordern */
Pool_Size = CONNECTION_POOL; Pool_Size = CONNECTION_POOL;
if ((Conf_MaxConnections > 0) && if ((Conf_MaxConnections > 0) &&
(Pool_Size > Conf_MaxConnections)) (Pool_Size > Conf_MaxConnections))
@@ -488,7 +454,7 @@ Conn_CloseAllSockets(int ExceptOf)
* @returns Number of listening sockets created. * @returns Number of listening sockets created.
*/ */
static unsigned int static unsigned int
Init_Listeners(array *a, const char *listen_addr, void (*func)(int,short)) ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
{ {
unsigned int created = 0; unsigned int created = 0;
size_t len; size_t len;
@@ -504,9 +470,8 @@ Init_Listeners(array *a, const char *listen_addr, void (*func)(int,short))
continue; continue;
} }
if (!io_event_create( fd, IO_WANTREAD, func )) { if (!io_event_create( fd, IO_WANTREAD, func )) {
Log(LOG_ERR, Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
"io_event_create(): Can't add fd %d (port %u): %s!", fd, (unsigned int) *port, strerror(errno));
fd, (unsigned int) *port, strerror(errno));
close(fd); close(fd);
port++; port++;
continue; continue;
@@ -528,76 +493,14 @@ Conn_InitListeners( void )
{ {
/* Initialize ports on which the server should accept connections */ /* Initialize ports on which the server should accept connections */
unsigned int created = 0; unsigned int created = 0;
char *af_str, *copy, *listen_addr; char *copy, *listen_addr;
int count, fd, i, addr_len;
ng_ipaddr_t addr;
assert(Conf_ListenAddress); assert(Conf_ListenAddress);
count = my_sd_listen_fds();
if (count < 0) {
Log(LOG_INFO,
"Not re-initializing listening sockets of systemd(8) ...");
return 0;
}
if (count > 0) {
/* systemd(8) passed sockets to us, so don't try to initialize
* listening sockets on our own but use the passed ones */
LogDebug("Initializing %d systemd sockets ...", count);
for (i = 0; i < count; i++) {
fd = SD_LISTEN_FDS_START + i;
addr_len = (int)sizeof(addr);
getsockname(fd, (struct sockaddr *)&addr, (socklen_t*)&addr_len);
#ifdef WANT_IPV6
if (addr.sin4.sin_family != AF_INET && addr.sin4.sin_family != AF_INET6)
#else
if (addr.sin4.sin_family != AF_INET)
#endif
{
/* Socket is of unsupported type! For example, systemd passed in
* an IPv6 socket but ngIRCd isn't compiled with IPv6 support. */
switch (addr.sin4.sin_family)
{
case AF_UNSPEC: af_str = "AF_UNSPEC"; break;
case AF_UNIX: af_str = "AF_UNIX"; break;
case AF_INET: af_str = "AF_INET"; break;
#ifdef AF_INET6
case AF_INET6: af_str = "AF_INET6"; break;
#endif
#ifdef AF_NETLINK
case AF_NETLINK: af_str = "AF_NETLINK"; break;
#endif
default: af_str = "unknown"; break;
}
Log(LOG_CRIT,
"Socket %d is of unsupported type \"%s\" (%d), have to ignore it!",
fd, af_str, addr.sin4.sin_family);
close(fd);
continue;
}
Init_Socket(fd);
if (!io_event_create(fd, IO_WANTREAD, cb_listen)) {
Log(LOG_ERR,
"io_event_create(): Can't add fd %d: %s!",
fd, strerror(errno));
continue;
}
Log(LOG_INFO,
"Initialized socket %d from systemd(8): %s:%d.", fd,
ng_ipaddr_tostr(&addr), ng_ipaddr_getport(&addr));
created++;
}
return created;
}
/* not using systemd socket activation, initialize listening sockets: */
/* can't use Conf_ListenAddress directly, see below */ /* can't use Conf_ListenAddress directly, see below */
copy = strdup(Conf_ListenAddress); copy = strdup(Conf_ListenAddress);
if (!copy) { if (!copy) {
Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
strerror(errno));
return 0; return 0;
} }
listen_addr = strtok(copy, ","); listen_addr = strtok(copy, ",");
@@ -605,11 +508,9 @@ Conn_InitListeners( void )
while (listen_addr) { while (listen_addr) {
ngt_TrimStr(listen_addr); ngt_TrimStr(listen_addr);
if (*listen_addr) { if (*listen_addr) {
created += Init_Listeners(&Conf_ListenPorts, created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
listen_addr, cb_listen);
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
created += Init_Listeners(&Conf_SSLOptions.ListenPorts, created += ports_initlisteners(&Conf_SSLOptions.ListenPorts, listen_addr, cb_listen_ssl);
listen_addr, cb_listen_ssl);
#endif #endif
} }
@@ -636,12 +537,7 @@ Conn_ExitListeners( void )
int *fd; int *fd;
size_t arraylen; size_t arraylen;
/* Get number of listening sockets to shut down. There can be none
* if ngIRCd has been "socket activated" by systemd. */
arraylen = array_length(&My_Listeners, sizeof (int)); arraylen = array_length(&My_Listeners, sizeof (int));
if (arraylen < 1)
return;
Log(LOG_INFO, Log(LOG_INFO,
"Shutting down all listening sockets (%d total) ...", arraylen); "Shutting down all listening sockets (%d total) ...", arraylen);
fd = array_start(&My_Listeners); fd = array_start(&My_Listeners);
@@ -672,7 +568,7 @@ InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port
ret = ng_ipaddr_init(addr, listen_addrstr, Port); ret = ng_ipaddr_init(addr, listen_addrstr, Port);
if (!ret) { if (!ret) {
assert(listen_addrstr); assert(listen_addrstr);
Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"!", Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
listen_addrstr, Port, listen_addrstr); listen_addrstr, Port, listen_addrstr);
} }
return ret; return ret;
@@ -724,9 +620,8 @@ NewListener(const char *listen_addr, UINT16 Port)
af = ng_ipaddr_af(&addr); af = ng_ipaddr_af(&addr);
sock = socket(af, SOCK_STREAM, 0); sock = socket(af, SOCK_STREAM, 0);
if (sock < 0) { if( sock < 0 ) {
Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
strerror(errno));
return -1; return -1;
} }
@@ -736,23 +631,22 @@ NewListener(const char *listen_addr, UINT16 Port)
return -1; return -1;
if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) { if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) {
Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s!", Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s",
ng_ipaddr_tostr(&addr), Port, strerror(errno)); ng_ipaddr_tostr(&addr), Port, strerror(errno));
close(sock); close(sock);
return -1; return -1;
} }
if (listen(sock, 10) != 0) { if( listen( sock, 10 ) != 0 ) {
Log(LOG_CRIT, "Can't listen on socket: %s!", strerror(errno)); Log( LOG_CRIT, "Can't listen on socket: %s!", strerror( errno ));
close(sock); close( sock );
return -1; return -1;
} }
/* keep fd in list so we can close it when ngircd restarts/shuts down */ /* keep fd in list so we can close it when ngircd restarts/shuts down */
if (!array_catb(&My_Listeners, (char *)&sock, sizeof(int))) { if (!array_catb( &My_Listeners,(char*) &sock, sizeof(int) )) {
Log(LOG_CRIT, "Can't add socket to My_Listeners array: %s!", Log( LOG_CRIT, "Can't add socket to My_Listeners array: %s!", strerror( errno ));
strerror(errno)); close( sock );
close(sock);
return -1; return -1;
} }
@@ -852,7 +746,8 @@ Conn_Handler(void)
/* Look for non-empty read buffers ... */ /* Look for non-empty read buffers ... */
for (i = 0; i < Pool_Size; i++) { for (i = 0; i < Pool_Size; i++) {
if ((My_Connections[i].sock > NONE) if ((My_Connections[i].sock > NONE)
&& (array_bytes(&My_Connections[i].rbuf) > 0)) { && (array_bytes(&My_Connections[i].rbuf) > 0)
&& (My_Connections[i].delaytime <= t)) {
/* ... and try to handle the received data */ /* ... and try to handle the received data */
bytes_processed = Handle_Buffer(i); bytes_processed = Handle_Buffer(i);
/* if we processed data, and there might be /* if we processed data, and there might be
@@ -922,7 +817,7 @@ Conn_Handler(void)
* which is the granularity with witch we handle "penalty * which is the granularity with witch we handle "penalty
* times" for example. * times" for example.
* Note: tv_sec/usec are undefined(!) after io_dispatch() * Note: tv_sec/usec are undefined(!) after io_dispatch()
* returns, so we have to set it before each call to it! */ * returns, so we have to set it beforce each call to it! */
tv.tv_usec = 0; tv.tv_usec = 0;
tv.tv_sec = 1; tv.tv_sec = 1;
@@ -935,15 +830,6 @@ Conn_Handler(void)
PACKAGE_NAME); PACKAGE_NAME);
exit(1); exit(1);
} }
/* Should ngIRCd timeout when idle? */
if (Conf_IdleTimeout > 0 && NumConnectionsAccepted > 0
&& idle_t > 0 && time(NULL) - idle_t >= Conf_IdleTimeout) {
LogDebug("Server idle timeout reached: %d second%s. Initiating shutdown ...",
Conf_IdleTimeout,
Conf_IdleTimeout == 1 ? "" : "s");
NGIRCd_SignalQuit = true;
}
} }
if (NGIRCd_SignalQuit) if (NGIRCd_SignalQuit)
@@ -1007,7 +893,7 @@ va_dcl
* *
* So we have a big problem here: we should send more bytes * So we have a big problem here: we should send more bytes
* to the network than we are allowed to and we don't know * to the network than we are allowed to and we don't know
* the originator (any more). The "old" behavior of blaming * the originator (any more). The "old" behaviour of blaming
* the receiver ("next hop") is a bad idea (it could be just * the receiver ("next hop") is a bad idea (it could be just
* an other server only routing the message!), so the only * an other server only routing the message!), so the only
* option left is to shorten the string and to hope that the * option left is to shorten the string and to hope that the
@@ -1181,8 +1067,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
/* Is this link already shutting down? */ /* Is this link already shutting down? */
if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) { if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) {
/* Conn_Close() has been called recursively for this link; /* Conn_Close() has been called recursively for this link;
* probable reason: Handle_Write() failed -- see below. */ * probabe reason: Handle_Write() failed -- see below. */
LogDebug("Recursive request to close connection %d!", Idx ); LogDebug("Recursive request to close connection: %d", Idx );
return; return;
} }
@@ -1192,7 +1078,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING ); Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
port = ng_ipaddr_getport(&My_Connections[Idx].addr); port = ng_ipaddr_getport(&My_Connections[Idx].addr);
Log(LOG_INFO, "Shutting down connection %d (%s) with \"%s:%d\" ...", Idx, Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx,
LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port); LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port);
/* Search client, if any */ /* Search client, if any */
@@ -1228,7 +1114,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
c = Conn_GetClient( Idx ); c = Conn_GetClient( Idx );
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) { if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
LogDebug("SSL connection %d shutting down ...", Idx); Log(LOG_INFO, "SSL connection %d shutting down ...", Idx);
ConnSSL_Free(&My_Connections[Idx]); ConnSSL_Free(&My_Connections[Idx]);
} }
#endif #endif
@@ -1266,7 +1152,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
in_p = (int)(( in_k * 100 ) / in_z_k ); in_p = (int)(( in_k * 100 ) / in_z_k );
out_p = (int)(( out_k * 100 ) / out_z_k ); out_p = (int)(( out_k * 100 ) / out_z_k );
Log(LOG_INFO, Log(LOG_INFO,
"Connection %d with \"%s:%d\" closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).", "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).",
Idx, My_Connections[Idx].host, port, Idx, My_Connections[Idx].host, port,
in_k, in_z_k, in_p, out_k, out_z_k, out_p); in_k, in_z_k, in_p, out_k, out_z_k, out_p);
} }
@@ -1274,7 +1160,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
#endif #endif
{ {
Log(LOG_INFO, Log(LOG_INFO,
"Connection %d with \"%s:%d\" closed (in: %.1fk, out: %.1fk).", "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).",
Idx, My_Connections[Idx].host, port, Idx, My_Connections[Idx].host, port,
in_k, out_k); in_k, out_k);
} }
@@ -1305,8 +1191,6 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
NumConnections--; NumConnections--;
LogDebug("Shutdown of connection %d completed, %ld connection%s left.", LogDebug("Shutdown of connection %d completed, %ld connection%s left.",
Idx, NumConnections, NumConnections != 1 ? "s" : ""); Idx, NumConnections, NumConnections != 1 ? "s" : "");
idle_t = NumConnections > 0 ? 0 : time(NULL);
} /* Conn_Close */ } /* Conn_Close */
@@ -1450,14 +1334,9 @@ Handle_Write( CONN_ID Idx )
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
return true; return true;
if (!Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ISCLOSING)) Log(LOG_ERR, "Write error on connection %d (socket %d): %s!",
Log(LOG_ERR, Idx, My_Connections[Idx].sock, strerror(errno));
"Write error on connection %d (socket %d): %s!", Conn_Close(Idx, "Write error!", NULL, false);
Idx, My_Connections[Idx].sock, strerror(errno));
else
LogDebug("Recursive write error on connection %d (socket %d): %s!",
Idx, My_Connections[Idx].sock, strerror(errno));
Conn_Close(Idx, "Write error", NULL, false);
return false; return false;
} }
@@ -1621,7 +1500,7 @@ New_Connection(int Sock, UNUSED bool IsSSL)
Client_SetHostname(c, My_Connections[new_sock].host); Client_SetHostname(c, My_Connections[new_sock].host);
Log(LOG_INFO, "Accepted connection %d from \"%s:%d\" on socket %d.", Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.",
new_sock, My_Connections[new_sock].host, new_sock, My_Connections[new_sock].host,
ng_ipaddr_getport(&new_addr), Sock); ng_ipaddr_getport(&new_addr), Sock);
Account_Connection(); Account_Connection();
@@ -1668,11 +1547,7 @@ Conn_StartLogin(CONN_ID Idx)
#endif #endif
(void)Conn_WriteStr(Idx, (void)Conn_WriteStr(Idx,
"NOTICE AUTH :*** Looking up your hostname"); "NOTICE AUTH :*** Looking up your hostname");
/* Send buffered data to the client, but break on errors (void)Handle_Write(Idx);
* because Handle_Write() would have closed the connection
* again in this case! */
if (!Handle_Write(Idx))
return;
} }
Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr, Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr,
@@ -1687,7 +1562,6 @@ static void
Account_Connection(void) Account_Connection(void)
{ {
NumConnections++; NumConnections++;
idle_t = 0;
if (NumConnections > NumConnectionsMax) if (NumConnections > NumConnectionsMax)
NumConnectionsMax = NumConnections; NumConnectionsMax = NumConnections;
LogDebug("Total number of connections now %lu (max %lu).", LogDebug("Total number of connections now %lu (max %lu).",
@@ -1717,7 +1591,7 @@ Socket2Index( int Sock )
/** /**
* Read data from the network to the read buffer. If an error occurs, * Read data from the network to the read buffer. If an error occures,
* the socket of this connection will be shut down. * the socket of this connection will be shut down.
* *
* @param Idx Connection index. * @param Idx Connection index.
@@ -1755,10 +1629,13 @@ Read_Request( CONN_ID Idx )
#endif #endif
len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf)); len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
if (len == 0) { if (len == 0) {
LogDebug("Client \"%s:%u\" is closing connection %d ...", Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
My_Connections[Idx].host, My_Connections[Idx].host,
ng_ipaddr_tostr(&My_Connections[Idx].addr), Idx); (unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr),
Conn_Close(Idx, NULL, "Client closed connection", false); ng_ipaddr_tostr(&My_Connections[Idx].addr));
Conn_Close(Idx,
"Socket closed!", "Client closed connection",
false);
return; return;
} }
@@ -1766,7 +1643,7 @@ Read_Request( CONN_ID Idx )
if( errno == EAGAIN ) return; if( errno == EAGAIN ) return;
Log(LOG_ERR, "Read error on connection %d (socket %d): %s!", Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
Idx, My_Connections[Idx].sock, strerror(errno)); Idx, My_Connections[Idx].sock, strerror(errno));
Conn_Close(Idx, "Read error", "Client closed connection", Conn_Close(Idx, "Read error!", "Client closed connection",
false); false);
return; return;
} }
@@ -1866,7 +1743,7 @@ Handle_Buffer(CONN_ID Idx)
maxcmd = (int)(Client_UserCount() / 5) maxcmd = (int)(Client_UserCount() / 5)
+ MAX_COMMANDS_SERVER_MIN; + MAX_COMMANDS_SERVER_MIN;
/* Allow servers to handle even more commands while peering /* Allow servers to handle even more commands while peering
* to speed up server login and network synchronization. */ * to speed up server login and network synchronisation. */
if (Conn_LastPing(Idx) == 0) if (Conn_LastPing(Idx) == 0)
maxcmd *= 5; maxcmd *= 5;
break; break;
@@ -2131,7 +2008,6 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (!ng_ipaddr_tostr_r(dest, ip_str)) { if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string"); Log(LOG_WARNING, "New_Server: Could not convert IP to string");
Conf_Server[Server].conn_id = NONE;
return; return;
} }
@@ -2146,14 +2022,11 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (new_sock < 0) { if (new_sock < 0) {
Log(LOG_CRIT, "Can't create socket (af %d): %s!", Log(LOG_CRIT, "Can't create socket (af %d): %s!",
af_dest, strerror(errno)); af_dest, strerror(errno));
Conf_Server[Server].conn_id = NONE;
return; return;
} }
if (!Init_Socket(new_sock)) { if (!Init_Socket(new_sock))
Conf_Server[Server].conn_id = NONE;
return; return;
}
/* is a bind address configured? */ /* is a bind address configured? */
res = ng_ipaddr_af(&Conf_Server[Server].bind_addr); res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
@@ -2169,7 +2042,6 @@ New_Server( int Server , ng_ipaddr_t *dest)
if(( res != 0 ) && ( errno != EINPROGRESS )) { if(( res != 0 ) && ( errno != EINPROGRESS )) {
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno )); Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
close( new_sock ); close( new_sock );
Conf_Server[Server].conn_id = NONE;
return; return;
} }
@@ -2178,14 +2050,12 @@ New_Server( int Server , ng_ipaddr_t *dest)
"Cannot allocate memory for server connection (socket %d)", "Cannot allocate memory for server connection (socket %d)",
new_sock); new_sock);
close( new_sock ); close( new_sock );
Conf_Server[Server].conn_id = NONE;
return; return;
} }
if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) { if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno)); Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
close(new_sock); close(new_sock);
Conf_Server[Server].conn_id = NONE;
return; return;
} }
@@ -2200,7 +2070,6 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (!c) { if (!c) {
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" ); Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
io_close(new_sock); io_close(new_sock);
Conf_Server[Server].conn_id = NONE;
return; return;
} }
@@ -2368,7 +2237,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
/** /**
* Read results of a resolver sub-process from the pipe and update the * Read results of a resolver sub-process from the pipe and update the
* appropriate connection/client structure(s): hostname and/or IDENT user name. * apropriate connection/client structure(s): hostname and/or IDENT user name.
* *
* @param r_fd File descriptor of the pipe to the sub-process. * @param r_fd File descriptor of the pipe to the sub-process.
* @param events (ignored IO specification) * @param events (ignored IO specification)
@@ -2462,27 +2331,21 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
*ptr ? "" : ": ", *ptr ? "" : ": ",
*ptr ? "" : identptr); *ptr ? "" : identptr);
} }
} else if(Conf_Ident) { } else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i); Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
if (Conf_NoticeAuth) if (Conf_NoticeAuth && Conf_Ident)
(void)Conn_WriteStr(i, (void)Conn_WriteStr(i,
"NOTICE AUTH :*** No ident response"); "NOTICE AUTH :*** No ident response");
} }
#endif #endif
if (Conf_NoticeAuth) { if (Conf_NoticeAuth)
/* Send buffered data to the client, but break on (void)Handle_Write(i);
* errors because Handle_Write() would have closed
* the connection again in this case! */
if (!Handle_Write(i))
return;
}
Class_HandleServerBans(c); Class_HandleServerBans(c);
} }
#ifdef DEBUG #ifdef DEBUG
else else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
LogDebug("Resolver: discarding result for already registered connection %d.", i);
#endif #endif
} /* cb_Read_Resolver_Result */ } /* cb_Read_Resolver_Result */
@@ -2601,7 +2464,7 @@ Conn_SetAuthPing(CONN_ID Idx, long ID)
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
/** /**
* Get information about used SSL cipher. * Get information about used SSL chiper.
* *
* @param Idx Connection index number. * @param Idx Connection index number.
* @param buf Buffer for returned information text. * @param buf Buffer for returned information text.
@@ -2633,45 +2496,6 @@ Conn_UsesSSL(CONN_ID Idx)
return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL); return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL);
} }
GLOBAL char *
Conn_GetCertFp(CONN_ID Idx)
{
if (Idx < 0)
return NULL;
assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
return ConnSSL_GetCertFp(&My_Connections[Idx]);
}
GLOBAL bool
Conn_SetCertFp(CONN_ID Idx, const char *fingerprint)
{
if (Idx < 0)
return false;
assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
return ConnSSL_SetCertFp(&My_Connections[Idx], fingerprint);
}
#else
GLOBAL bool
Conn_UsesSSL(UNUSED CONN_ID Idx)
{
return false;
}
GLOBAL char *
Conn_GetCertFp(UNUSED CONN_ID Idx)
{
return NULL;
}
GLOBAL bool
Conn_SetCertFp(UNUSED CONN_ID Idx, UNUSED const char *fingerprint)
{
return true;
}
#endif #endif

View File

@@ -139,12 +139,13 @@ GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd));
GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i)); GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i)); GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i));
GLOBAL char *Conn_GetCertFp PARAMS((CONN_ID Idx));
GLOBAL bool Conn_SetCertFp PARAMS((CONN_ID Idx, const char *fingerprint));
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len)); GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
#else
static inline bool
Conn_UsesSSL(UNUSED CONN_ID Idx)
{ return false; }
#endif #endif
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx)); GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -36,7 +36,7 @@
/* Generic buffer sizes */ /* Generic buffer sizes */
/** Max. length of a line in the configuration file. */ /** Max. length of a line in the configuration file. */
#define LINE_LEN 1024 #define LINE_LEN 256
/** Max. length of a log message. */ /** Max. length of a log message. */
#define MAX_LOG_MSG_LEN 256 #define MAX_LOG_MSG_LEN 256
@@ -50,6 +50,7 @@
/** Max. length of random salt */ /** Max. length of random salt */
#define RANDOM_SALT_LEN 32 #define RANDOM_SALT_LEN 32
/* Size of structures */ /* Size of structures */
/** Max. count of configurable servers. */ /** Max. count of configurable servers. */
@@ -73,15 +74,9 @@
/** Configuration file name. */ /** Configuration file name. */
#define CONFIG_FILE "/ngircd.conf" #define CONFIG_FILE "/ngircd.conf"
/** Directory containing optional configuration snippets. */
#define CONFIG_DIR "/ngircd.conf.d"
/** Name of the MOTD file. */ /** Name of the MOTD file. */
#define MOTD_FILE "/ngircd.motd" #define MOTD_FILE "/ngircd.motd"
/** Name of the help file. */
#define HELP_FILE "/Commands.txt"
/** Default chroot() directory. */ /** Default chroot() directory. */
#define CHROOT_DIR "" #define CHROOT_DIR ""
@@ -101,7 +96,7 @@
#define CLIENT_NICK_LEN 32 #define CLIENT_NICK_LEN 32
/** Max. password length (including NULL). */ /** Max. password length (including NULL). */
#define CLIENT_PASS_LEN 65 #define CLIENT_PASS_LEN 21
/** Max. length of user name ("login"; incl. NULL), RFC 2812, section 1.2.1. */ /** Max. length of user name ("login"; incl. NULL), RFC 2812, section 1.2.1. */
#ifndef STRICT_RFC #ifndef STRICT_RFC
@@ -116,9 +111,6 @@
/** Max. host name length (including NULL). */ /** Max. host name length (including NULL). */
#define CLIENT_HOST_LEN 64 #define CLIENT_HOST_LEN 64
/** Max. mask lenght (including NULL). */
#define MASK_LEN (2 * CLIENT_HOST_LEN)
/** Max. length of all client modes (including NULL). */ /** Max. length of all client modes (including NULL). */
#define CLIENT_MODE_LEN 21 #define CLIENT_MODE_LEN 21
@@ -178,9 +170,6 @@
/** Supported channel modes. */ /** Supported channel modes. */
#define CHANMODES "abehiIklmMnoOPqQrRstvVz" #define CHANMODES "abehiIklmMnoOPqQrRstvVz"
/** Supported channel types. */
#define CHANTYPES "#&+"
/** Away message for users connected to linked servers. */ /** Away message for users connected to linked servers. */
#define DEFAULT_AWAY_MSG "Away" #define DEFAULT_AWAY_MSG "Away"

View File

@@ -37,7 +37,7 @@ static UINT32 jenkins_hash PARAMS((UINT8 *k, UINT32 length, UINT32 initval));
GLOBAL UINT32 GLOBAL UINT32
Hash( const char *String ) Hash( const char *String )
{ {
char buffer[COMMAND_LEN]; char buffer[LINE_LEN];
strlcpy(buffer, String, sizeof(buffer)); strlcpy(buffer, String, sizeof(buffer));
return jenkins_hash((UINT8 *)ngt_LowerStr(buffer), return jenkins_hash((UINT8 *)ngt_LowerStr(buffer),

View File

@@ -631,7 +631,7 @@ io_library_init_kqueue(unsigned int eventsize)
io_masterfd = kqueue(); io_masterfd = kqueue();
Log(LOG_INFO, Log(LOG_INFO,
"IO subsystem: kqueue (initial maxfd %u, masterfd %d).", "IO subsystem: kqueue (initial maxfd %u, masterfd %d)",
eventsize, io_masterfd); eventsize, io_masterfd);
if (io_masterfd >= 0) if (io_masterfd >= 0)
library_initialized = true; library_initialized = true;

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@
#include "conn.h" #include "conn.h"
#include "channel.h" #include "channel.h"
#include "client-cap.h" #include "client-cap.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "log.h" #include "log.h"
#include "login.h" #include "login.h"
@@ -34,14 +33,192 @@
#include "exp.h" #include "exp.h"
#include "irc-cap.h" #include "irc-cap.h"
/* Local functions */ bool Handle_CAP_LS PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_LIST PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_REQ PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_ACK PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_CLEAR PARAMS((CLIENT *Client));
bool Handle_CAP_END PARAMS((CLIENT *Client));
void Set_CAP_Negotiation PARAMS((CLIENT *Client));
int Parse_CAP PARAMS((int Capabilities, char *Args));
char *Get_CAP_String PARAMS((int Capabilities));
/**
* Handler for the IRCv3 "CAP" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_CAP(CLIENT *Client, REQUEST *Req)
{
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of prameters? */
if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
LogDebug("Got \"%s %s\" command from \"%s\" ...",
Req->command, Req->argv[0], Client_ID(Client));
if (Req->argc == 1) {
if (strcasecmp(Req->argv[0], "CLEAR") == 0)
return Handle_CAP_CLEAR(Client);
if (strcasecmp(Req->argv[0], "END") == 0)
return Handle_CAP_END(Client);
}
if (Req->argc >= 1 && Req->argc <= 2) {
if (strcasecmp(Req->argv[0], "LS") == 0)
return Handle_CAP_LS(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "LIST") == 0)
return Handle_CAP_LIST(Client, Req->argv[1]);
}
if (Req->argc == 2) {
if (strcasecmp(Req->argv[0], "REQ") == 0)
return Handle_CAP_REQ(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "ACK") == 0)
return Handle_CAP_ACK(Client, Req->argv[1]);
}
return IRC_WriteStrClient(Client, ERR_INVALIDCAP_MSG,
Client_ID(Client), Req->argv[0]);
}
/**
* Handler for the "CAP LS" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
Set_CAP_Negotiation(Client);
return IRC_WriteStrClient(Client,
"CAP %s LS :multi-prefix",
Client_ID(Client));
}
/**
* Handler for the "CAP LIST" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
return IRC_WriteStrClient(Client, "CAP %s LIST :%s", Client_ID(Client),
Get_CAP_String(Client_Cap(Client)));
}
/**
* Handler for the "CAP REQ" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_REQ(CLIENT *Client, char *Arg)
{
int new_cap;
assert(Client != NULL);
assert(Arg != NULL);
Set_CAP_Negotiation(Client);
new_cap = Parse_CAP(Client_Cap(Client), Arg);
if (new_cap < 0)
return IRC_WriteStrClient(Client, "CAP %s NAK :%s",
Client_ID(Client), Arg);
Client_CapSet(Client, new_cap);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s",
Client_ID(Client), Arg);
}
/**
* Handler for the "CAP ACK" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
assert(Arg != NULL);
return CONNECTED;
}
/**
* Handler for the "CAP CLEAR" command.
*
* @param Client The client from which this command has been received.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_CLEAR(CLIENT *Client)
{
int cap_old;
assert(Client != NULL);
cap_old = Client_Cap(Client);
if (cap_old & CLIENT_CAP_MULTI_PREFIX)
Client_CapDel(Client, CLIENT_CAP_MULTI_PREFIX);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client),
Get_CAP_String(cap_old));
}
/**
* Handler for the "CAP END" command.
*
* @param Client The client from which this command has been received.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_END(CLIENT *Client)
{
assert(Client != NULL);
if (Client_Type(Client) != CLIENT_USER) {
/* User is still logging in ... */
Client_CapDel(Client, CLIENT_CAP_PENDING);
if (Client_Type(Client) == CLIENT_WAITCAPEND) {
/* Only "CAP END" was missing: log in! */
return Login_User(Client);
}
}
return CONNECTED;
}
/** /**
* Set CAP negotiation status and mark client as "supports capabilities". * Set CAP negotiation status and mark client as "supports capabilities".
* *
* @param Client The client to handle. * @param Client The client to handle.
*/ */
static void void
Set_CAP_Negotiation(CLIENT *Client) Set_CAP_Negotiation(CLIENT *Client)
{ {
assert(Client != NULL); assert(Client != NULL);
@@ -57,7 +234,7 @@ Set_CAP_Negotiation(CLIENT *Client)
* @param Args The string containing space-separated capability names. * @param Args The string containing space-separated capability names.
* @return Changed capability flags or 0 on error. * @return Changed capability flags or 0 on error.
*/ */
static int int
Parse_CAP(int Capabilities, char *Args) Parse_CAP(int Capabilities, char *Args)
{ {
static char tmp[COMMAND_LEN]; static char tmp[COMMAND_LEN];
@@ -98,7 +275,7 @@ Parse_CAP(int Capabilities, char *Args)
* @param Capabilities Capability flags (bitmask). * @param Capabilities Capability flags (bitmask).
* @return Pointer to textual representation. * @return Pointer to textual representation.
*/ */
static char * char *
Get_CAP_String(int Capabilities) Get_CAP_String(int Capabilities)
{ {
static char txt[COMMAND_LEN]; static char txt[COMMAND_LEN];
@@ -111,169 +288,4 @@ Get_CAP_String(int Capabilities)
return txt; return txt;
} }
/**
* Handler for the IRCv3 sub-command "CAP LS".
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
Set_CAP_Negotiation(Client);
return IRC_WriteStrClient(Client,
"CAP %s LS :multi-prefix",
Client_ID(Client));
}
/**
* Handler for the IRCv3 sub-command "CAP LIST".
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
return IRC_WriteStrClient(Client, "CAP %s LIST :%s", Client_ID(Client),
Get_CAP_String(Client_Cap(Client)));
}
/**
* Handler for the IRCv3 sub-command "CAP REQ".
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_REQ(CLIENT *Client, char *Arg)
{
int new_cap;
assert(Client != NULL);
assert(Arg != NULL);
Set_CAP_Negotiation(Client);
new_cap = Parse_CAP(Client_Cap(Client), Arg);
if (new_cap < 0)
return IRC_WriteStrClient(Client, "CAP %s NAK :%s",
Client_ID(Client), Arg);
Client_CapSet(Client, new_cap);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s",
Client_ID(Client), Arg);
}
/**
* Handler for the IRCv3 sub-command "CAP ACK".
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
assert(Arg != NULL);
return CONNECTED;
}
/**
* Handler for the IRCv3 sub-command "CAP CLEAR".
*
* @param Client The client from which this command has been received.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_CLEAR(CLIENT *Client)
{
int cap_old;
assert(Client != NULL);
cap_old = Client_Cap(Client);
if (cap_old & CLIENT_CAP_MULTI_PREFIX)
Client_CapDel(Client, CLIENT_CAP_MULTI_PREFIX);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client),
Get_CAP_String(cap_old));
}
/**
* Handler for the IRCv3 sub-command "CAP END".
*
* @param Client The client from which this command has been received.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Handle_CAP_END(CLIENT *Client)
{
assert(Client != NULL);
if (Client_Type(Client) != CLIENT_USER) {
/* User is still logging in ... */
Client_CapDel(Client, CLIENT_CAP_PENDING);
if (Client_Type(Client) == CLIENT_WAITCAPEND) {
/* Only "CAP END" was missing: log in! */
return Login_User(Client);
}
}
return CONNECTED;
}
/* Global functions */
/**
* Handler for the IRCv3 command "CAP".
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_CAP(CLIENT *Client, REQUEST *Req)
{
assert(Client != NULL);
assert(Req != NULL);
LogDebug("Got \"%s %s\" command from \"%s\" ...",
Req->command, Req->argv[0], Client_ID(Client));
if (Req->argc == 1) {
if (strcasecmp(Req->argv[0], "CLEAR") == 0)
return Handle_CAP_CLEAR(Client);
if (strcasecmp(Req->argv[0], "END") == 0)
return Handle_CAP_END(Client);
}
if (Req->argc >= 1 && Req->argc <= 2) {
if (strcasecmp(Req->argv[0], "LS") == 0)
return Handle_CAP_LS(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "LIST") == 0)
return Handle_CAP_LIST(Client, Req->argv[1]);
}
if (Req->argc == 2) {
if (strcasecmp(Req->argv[0], "REQ") == 0)
return Handle_CAP_REQ(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "ACK") == 0)
return Handle_CAP_ACK(Client, Req->argv[1]);
}
return IRC_WriteErrClient(Client, ERR_INVALIDCAP_MSG,
Client_ID(Client), Req->argv[0]);
}
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -33,13 +33,13 @@
#include "parse.h" #include "parse.h"
#include "irc.h" #include "irc.h"
#include "irc-info.h" #include "irc-info.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "conf.h" #include "conf.h"
#include "exp.h" #include "exp.h"
#include "irc-channel.h" #include "irc-channel.h"
/** /**
* Part from all channels. * Part from all channels.
* *
@@ -67,6 +67,7 @@ part_from_all_channels(CLIENT* client, CLIENT *target)
return CONNECTED; return CONNECTED;
} /* part_from_all_channels */ } /* part_from_all_channels */
/** /**
* Check weather a local client is allowed to join an already existing * Check weather a local client is allowed to join an already existing
* channel or not. * channel or not.
@@ -82,9 +83,10 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
const char *key) const char *key)
{ {
bool is_invited, is_banned, is_exception; bool is_invited, is_banned, is_exception;
const char *channel_modes;
/* Allow IRC operators to overwrite channel limits */ /* Allow IRC operators to overwrite channel limits */
if (Client_HasMode(Client, 'o')) if (strchr(Client_Modes(Client), 'o'))
return true; return true;
is_banned = Lists_Check(Channel_GetListBans(chan), Client); is_banned = Lists_Check(Channel_GetListBans(chan), Client);
@@ -93,14 +95,15 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
if (is_banned && !is_invited && !is_exception) { if (is_banned && !is_invited && !is_exception) {
/* Client is banned from channel (and not on invite list) */ /* Client is banned from channel (and not on invite list) */
IRC_WriteErrClient(Client, ERR_BANNEDFROMCHAN_MSG, IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
if (Channel_HasMode(chan, 'i') && !is_invited) { channel_modes = Channel_Modes(chan);
if (strchr(channel_modes, 'i') && !is_invited) {
/* Channel is "invite-only" and client is not on invite list */ /* Channel is "invite-only" and client is not on invite list */
IRC_WriteErrClient(Client, ERR_INVITEONLYCHAN_MSG, IRC_WriteStrClient(Client, ERR_INVITEONLYCHAN_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
@@ -108,37 +111,37 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
if (!Channel_CheckKey(chan, Client, key ? key : "")) { if (!Channel_CheckKey(chan, Client, key ? key : "")) {
/* Channel is protected by a channel key and the client /* Channel is protected by a channel key and the client
* didn't specify the correct one */ * didn't specify the correct one */
IRC_WriteErrClient(Client, ERR_BADCHANNELKEY_MSG, IRC_WriteStrClient(Client, ERR_BADCHANNELKEY_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
if (Channel_HasMode(chan, 'l') && if (strchr(channel_modes, 'l') &&
(Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) { (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) {
/* There are more clints joined to this channel than allowed */ /* There are more clints joined to this channel than allowed */
IRC_WriteErrClient(Client, ERR_CHANNELISFULL_MSG, IRC_WriteStrClient(Client, ERR_CHANNELISFULL_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
if (Channel_HasMode(chan, 'z') && !Conn_UsesSSL(Client_Conn(Client))) { if (strchr(channel_modes, 'z') && !Conn_UsesSSL(Client_Conn(Client))) {
/* Only "secure" clients are allowed, but clients doesn't /* Only "secure" clients are allowed, but clients doesn't
* use SSL encryption */ * use SSL encryption */
IRC_WriteErrClient(Client, ERR_SECURECHANNEL_MSG, IRC_WriteStrClient(Client, ERR_SECURECHANNEL_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
if (Channel_HasMode(chan, 'O') && !Client_HasMode(Client, 'o')) { if (strchr(channel_modes, 'O') && !Client_OperByMe(Client)) {
/* Only IRC operators are allowed! */ /* Only IRC operators are allowed! */
IRC_WriteErrClient(Client, ERR_OPONLYCHANNEL_MSG, IRC_WriteStrClient(Client, ERR_OPONLYCHANNEL_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
if (Channel_HasMode(chan, 'R') && !Client_HasMode(Client, 'R')) { if (strchr(channel_modes, 'R') && !strchr(Client_Modes(Client), 'R')) {
/* Only registered users are allowed! */ /* Only registered users are allowed! */
IRC_WriteErrClient(Client, ERR_REGONLYCHANNEL_MSG, IRC_WriteStrClient(Client, ERR_REGONLYCHANNEL_MSG,
Client_ID(Client), channame); Client_ID(Client), channame);
return false; return false;
} }
@@ -146,6 +149,7 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
return true; return true;
} /* join_allowed */ } /* join_allowed */
/** /**
* Set user channel modes. * Set user channel modes.
* *
@@ -165,15 +169,16 @@ join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags)
/* If the channel is persistent (+P) and client is an IRC op: /* If the channel is persistent (+P) and client is an IRC op:
* make client chanop, if not disabled in configuration. */ * make client chanop, if not disabled in configuration. */
if (Channel_HasMode(chan, 'P') && Conf_OperChanPAutoOp if (strchr(Channel_Modes(chan), 'P') && Conf_OperChanPAutoOp
&& Client_HasMode(target, 'o')) && strchr(Client_Modes(target), 'o'))
Channel_UserModeAdd(chan, target, 'o'); Channel_UserModeAdd(chan, target, 'o');
} /* join_set_channelmodes */ } /* join_set_channelmodes */
/** /**
* Forward JOIN command to a specific server * Forward JOIN command to a specific server
* *
* This function differentiates between servers using RFC 2813 mode that * This function diffentiates between servers using RFC 2813 mode that
* support the JOIN command with appended ASCII 7 character and channel * support the JOIN command with appended ASCII 7 character and channel
* modes, and servers using RFC 1459 protocol which require separate JOIN * modes, and servers using RFC 1459 protocol which require separate JOIN
* and MODE commands. * and MODE commands.
@@ -206,6 +211,7 @@ cb_join_forward(CLIENT *To, CLIENT *Prefix, void *Data)
Client_ID(Prefix)); Client_ID(Prefix));
} /* cb_join_forward */ } /* cb_join_forward */
/** /**
* Forward JOIN command to all servers * Forward JOIN command to all servers
* *
@@ -250,8 +256,9 @@ join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan,
} }
} /* join_forward */ } /* join_forward */
/** /**
* Acknowledge user JOIN request and send "channel info" numerics. * Aknowledge user JOIN request and send "channel info" numerics.
* *
* @param Client Client used to prefix the genrated commands * @param Client Client used to prefix the genrated commands
* @param target Forward commands/numerics to this user * @param target Forward commands/numerics to this user
@@ -292,12 +299,15 @@ join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan,
Channel_Name(chan)); Channel_Name(chan));
} /* join_send_topic */ } /* join_send_topic */
/** /**
* Handler for the IRC "JOIN" command. * Handler for the IRC "JOIN" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.2.1 "Join message"; RFC 2813, 4.2.1 "Join message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
*/ */
GLOBAL bool GLOBAL bool
IRC_JOIN( CLIENT *Client, REQUEST *Req ) IRC_JOIN( CLIENT *Client, REQUEST *Req )
@@ -309,7 +319,20 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
assert (Client != NULL); assert (Client != NULL);
assert (Req != NULL); assert (Req != NULL);
_IRC_GET_SENDER_OR_RETURN_(target, Req, Client) /* Bad number of arguments? */
if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Who is the sender? */
if (Client_Type(Client) == CLIENT_SERVER)
target = Client_Search(Req->prefix);
else
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Is argument "0"? */ /* Is argument "0"? */
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2)) if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
@@ -323,11 +346,9 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
channame = strtok_r(channame, ",", &lastchan); channame = strtok_r(channame, ",", &lastchan);
/* Make sure that "channame" is not the empty string ("JOIN :") */ /* Make sure that "channame" is not the empty string ("JOIN :") */
if (!channame) { if (! channame)
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
}
while (channame) { while (channame) {
flags = NULL; flags = NULL;
@@ -342,6 +363,12 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
} }
chan = Channel_Search(channame); chan = Channel_Search(channame);
if (!chan && Conf_PredefChannelsOnly) {
/* channel must be created, but forbidden by config */
IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG,
Client_ID(Client), channame);
goto join_next;
}
/* Local client? */ /* Local client? */
if (Client_Type(Client) == CLIENT_USER) { if (Client_Type(Client) == CLIENT_USER) {
@@ -349,21 +376,12 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
/* Already existing channel: already member? */ /* Already existing channel: already member? */
if (Channel_IsMemberOf(chan, Client)) if (Channel_IsMemberOf(chan, Client))
goto join_next; goto join_next;
} else {
/* Channel must be created */
if (!strchr(Conf_AllowedChannelTypes, channame[0])) {
/* ... but channel type is not allowed! */
IRC_WriteErrClient(Client,
ERR_NOSUCHCHANNEL_MSG,
Client_ID(Client), channame);
goto join_next;
}
} }
/* Test if the user has reached the channel limit */ /* Test if the user has reached the channel limit */
if ((Conf_MaxJoins > 0) && if ((Conf_MaxJoins > 0) &&
(Channel_CountForUser(Client) >= Conf_MaxJoins)) { (Channel_CountForUser(Client) >= Conf_MaxJoins)) {
if (!IRC_WriteErrClient(Client, if (!IRC_WriteStrClient(Client,
ERR_TOOMANYCHANNELS_MSG, ERR_TOOMANYCHANNELS_MSG,
Client_ID(Client), channame)) Client_ID(Client), channame))
return DISCONNECTED; return DISCONNECTED;
@@ -425,12 +443,15 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
return CONNECTED; return CONNECTED;
} /* IRC_JOIN */ } /* IRC_JOIN */
/** /**
* Handler for the IRC "PART" command. * Handler for the IRC "PART" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.2.2: "Part message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
*/ */
GLOBAL bool GLOBAL bool
IRC_PART(CLIENT * Client, REQUEST * Req) IRC_PART(CLIENT * Client, REQUEST * Req)
@@ -441,17 +462,26 @@ IRC_PART(CLIENT * Client, REQUEST * Req)
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
_IRC_GET_SENDER_OR_RETURN_(target, Req, Client) if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Get the sender */
if (Client_Type(Client) == CLIENT_SERVER)
target = Client_Search(Req->prefix);
else
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Loop over all the given channel names */ /* Loop over all the given channel names */
chan = strtok(Req->argv[0], ","); chan = strtok(Req->argv[0], ",");
/* Make sure that "chan" is not the empty string ("PART :") */ /* Make sure that "chan" is not the empty string ("PART :") */
if (!chan) { if (! chan)
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
}
while (chan) { while (chan) {
Channel_Part(target, Client, chan, Channel_Part(target, Client, chan,
@@ -466,12 +496,15 @@ IRC_PART(CLIENT * Client, REQUEST * Req)
return CONNECTED; return CONNECTED;
} /* IRC_PART */ } /* IRC_PART */
/** /**
* Handler for the IRC "TOPIC" command. * Handler for the IRC "TOPIC" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.2.4 "Topic message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
*/ */
GLOBAL bool GLOBAL bool
IRC_TOPIC( CLIENT *Client, REQUEST *Req ) IRC_TOPIC( CLIENT *Client, REQUEST *Req )
@@ -484,23 +517,32 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req )
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
IRC_SetPenalty(Client, 1); if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
chan = Channel_Search(Req->argv[0]); chan = Channel_Search(Req->argv[0]);
if (!chan) if (!chan)
return IRC_WriteErrClient(from, ERR_NOSUCHCHANNEL_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHCHANNEL_MSG,
Client_ID(from), Req->argv[0]); Client_ID(from), Req->argv[0]);
/* Only remote servers and channel members are allowed to change the /* Only remote servers and channel members are allowed to change the
* channel topic, and IRC operators when the Conf_OperCanMode option * channel topic, and IRC opreators when the Conf_OperCanMode option
* is set in the server configuration. */ * is set in the server configuration. */
if (Client_Type(Client) != CLIENT_SERVER) { if (Client_Type(Client) != CLIENT_SERVER) {
topic_power = Client_HasMode(from, 'o'); topic_power = Client_HasMode(from, 'o');
if (!Channel_IsMemberOf(chan, from) if (!Channel_IsMemberOf(chan, from)
&& !(Conf_OperCanMode && topic_power)) && !(Conf_OperCanMode && topic_power))
return IRC_WriteErrClient(from, ERR_NOTONCHANNEL_MSG, return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG,
Client_ID(from), Req->argv[0]); Client_ID(from), Req->argv[0]);
} else } else
topic_power = true; topic_power = true;
@@ -529,14 +571,14 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req )
Channel_Name(chan)); Channel_Name(chan));
} }
if (Channel_HasMode(chan, 't')) { if (strchr(Channel_Modes(chan), 't')) {
/* Topic Lock. Is the user a channel op or IRC operator? */ /* Topic Lock. Is the user a channel op or IRC operator? */
if(!topic_power && if(!topic_power &&
!Channel_UserHasMode(chan, from, 'h') && !strchr(Channel_UserModes(chan, from), 'h') &&
!Channel_UserHasMode(chan, from, 'o') && !strchr(Channel_UserModes(chan, from), 'o') &&
!Channel_UserHasMode(chan, from, 'a') && !strchr(Channel_UserModes(chan, from), 'a') &&
!Channel_UserHasMode(chan, from, 'q')) !strchr(Channel_UserModes(chan, from), 'q'))
return IRC_WriteErrClient(from, ERR_CHANOPRIVSNEEDED_MSG, return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(from), Client_ID(from),
Channel_Name(chan)); Channel_Name(chan));
} }
@@ -564,9 +606,15 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req )
return CONNECTED; return CONNECTED;
} /* IRC_TOPIC */ } /* IRC_TOPIC */
/** /**
* Handler for the IRC "LIST" command. * Handler for the IRC "LIST" command.
* *
* See RFC 2812, 3.2.6 "List message".
*
* This implementation handles the local case as well as the forwarding of the
* LIST command to other servers in the IRC network.
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -582,20 +630,31 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
IRC_SetPenalty(Client, 2); /* Bad number of prameters? */
if (Req->argc > 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Req->argc > 0) if (Req->argc > 0)
pattern = strtok(Req->argv[0], ","); pattern = strtok(Req->argv[0], ",");
else else
pattern = "*"; pattern = "*";
/* Get sender from prefix, if any */
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->prefix);
if (Req->argc == 2) { if (Req->argc == 2) {
/* Forward to other server? */ /* Forward to other server? */
target = Client_Search(Req->argv[1]); target = Client_Search(Req->argv[1]);
if (! target || Client_Type(target) != CLIENT_SERVER) if (! target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Client_ID(Client),
Req->argv[1]); Req->argv[1]);
@@ -617,12 +676,9 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
/* Check search pattern */ /* Check search pattern */
if (MatchCaseInsensitive(pattern, Channel_Name(chan))) { if (MatchCaseInsensitive(pattern, Channel_Name(chan))) {
/* Gotcha! */ /* Gotcha! */
if (!Channel_HasMode(chan, 's') if (!strchr(Channel_Modes(chan), 's')
|| Channel_IsMemberOf(chan, from) || Channel_IsMemberOf(chan, from)
|| (!Conf_MorePrivacy || (!Conf_MorePrivacy && Client_OperByMe(Client))) {
&& Client_HasMode(Client, 'o')
&& Client_Conn(Client) > NONE))
{
if ((Conf_MaxListSize > 0) if ((Conf_MaxListSize > 0)
&& IRC_CheckListTooBig(from, count, && IRC_CheckListTooBig(from, count,
Conf_MaxListSize, Conf_MaxListSize,
@@ -647,20 +703,25 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
pattern = NULL; pattern = NULL;
} }
IRC_SetPenalty(from, 2);
return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from)); return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from));
} /* IRC_LIST */ } /* IRC_LIST */
/** /**
* Handler for the IRC+ "CHANINFO" command. * Handler for the IRC+ command "CHANINFO".
* *
* @param Client The client from which this command has been received. * See doc/Protocol.txt, section II.3:
* @param Req Request structure with prefix and all parameters. * "Exchange channel-modes, topics, and persistent channels".
* @return CONNECTED or DISCONNECTED. *
* @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
*/ */
GLOBAL bool GLOBAL bool
IRC_CHANINFO( CLIENT *Client, REQUEST *Req ) IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
{ {
char modes_add[COMMAND_LEN], l[16]; char modes_add[COMMAND_LEN], l[16], *ptr;
CLIENT *from; CLIENT *from;
CHANNEL *chan; CHANNEL *chan;
int arg_topic; int arg_topic;
@@ -669,70 +730,73 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
assert( Req != NULL ); assert( Req != NULL );
/* Bad number of parameters? */ /* Bad number of parameters? */
if (Req->argc < 2 || Req->argc == 4 || Req->argc > 5) { if (Req->argc < 2 || Req->argc == 4 || Req->argc > 5)
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
}
/* Compatibility kludge */ /* Compatibility kludge */
if (Req->argc == 5) if( Req->argc == 5 ) arg_topic = 4;
arg_topic = 4; else if( Req->argc == 3 ) arg_topic = 2;
else if(Req->argc == 3) else arg_topic = -1;
arg_topic = 2;
else
arg_topic = -1;
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) /* Search origin */
from = Client_Search( Req->prefix );
if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Search or create channel */ /* Search or create channel */
chan = Channel_Search( Req->argv[0] ); chan = Channel_Search( Req->argv[0] );
if (!chan) if( ! chan ) chan = Channel_Create( Req->argv[0] );
chan = Channel_Create( Req->argv[0] ); if( ! chan ) return CONNECTED;
if (!chan)
return CONNECTED;
if (Req->argv[1][0] == '+') { if( Req->argv[1][0] == '+' )
if (!*Channel_Modes(chan)) { {
/* OK, this channel doesn't have modes yet, ptr = Channel_Modes( chan );
* set the received ones: */ if( ! *ptr )
Channel_SetModes(chan, &Req->argv[1][1]); {
/* OK, this channel doesn't have modes jet, set the received ones: */
Channel_SetModes( chan, &Req->argv[1][1] );
if(Req->argc == 5) { if( Req->argc == 5 )
if(Channel_HasMode(chan, 'k')) {
Channel_SetKey(chan, Req->argv[2]); if( strchr( Channel_Modes( chan ), 'k' )) Channel_SetKey( chan, Req->argv[2] );
if(Channel_HasMode(chan, 'l')) if( strchr( Channel_Modes( chan ), 'l' )) Channel_SetMaxUsers( chan, atol( Req->argv[3] ));
Channel_SetMaxUsers(chan, atol(Req->argv[3])); }
} else { else
{
/* Delete modes which we never want to inherit */ /* Delete modes which we never want to inherit */
Channel_ModeDel(chan, 'l'); Channel_ModeDel( chan, 'l' );
Channel_ModeDel(chan, 'k'); Channel_ModeDel( chan, 'k' );
} }
strcpy(modes_add, ""); strcpy( modes_add, "" );
if (Channel_HasMode(chan, 'l')) { ptr = Channel_Modes( chan );
snprintf(l, sizeof(l), " %lu", while( *ptr )
Channel_MaxUsers(chan)); {
strlcat(modes_add, l, sizeof(modes_add)); if( *ptr == 'l' )
} {
if (Channel_HasMode(chan, 'k')) { snprintf( l, sizeof( l ), " %lu", Channel_MaxUsers( chan ));
strlcat(modes_add, " ", sizeof(modes_add)); strlcat( modes_add, l, sizeof( modes_add ));
strlcat(modes_add, Channel_Key(chan), }
sizeof(modes_add)); if( *ptr == 'k' )
{
strlcat( modes_add, " ", sizeof( modes_add ));
strlcat( modes_add, Channel_Key( chan ), sizeof( modes_add ));
}
ptr++;
} }
/* Inform members of this channel */ /* Inform members of this channel */
IRC_WriteStrChannelPrefix(Client, chan, from, false, IRC_WriteStrChannelPrefix( Client, chan, from, false, "MODE %s +%s%s", Req->argv[0], Channel_Modes( chan ), modes_add );
"MODE %s +%s%s", Req->argv[0],
Channel_Modes(chan), modes_add);
} }
} }
else else Log( LOG_WARNING, "CHANINFO: invalid MODE format ignored!" );
Log(LOG_WARNING, "CHANINFO: invalid MODE format ignored!");
if (arg_topic > 0) { if( arg_topic > 0 )
{
/* We got a topic */ /* We got a topic */
if (!*Channel_Topic(chan) && Req->argv[arg_topic][0]) { ptr = Channel_Topic( chan );
if(( ! *ptr ) && ( Req->argv[arg_topic][0] ))
{
/* OK, there is no topic jet */ /* OK, there is no topic jet */
Channel_SetTopic(chan, Client, Req->argv[arg_topic]); Channel_SetTopic(chan, Client, Req->argv[arg_topic]);
IRC_WriteStrChannelPrefix(Client, chan, from, false, IRC_WriteStrChannelPrefix(Client, chan, from, false,
@@ -740,24 +804,13 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
} }
} }
/* Forward CHANINFO to other servers */ /* Forward CHANINFO to other serevrs */
if (Req->argc == 5) if( Req->argc == 5 ) IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s %s %s :%s", Req->argv[0], Req->argv[1], Req->argv[2], Req->argv[3], Req->argv[4] );
IRC_WriteStrServersPrefixFlag(Client, from, 'C', else if( Req->argc == 3 ) IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s :%s", Req->argv[0], Req->argv[1], Req->argv[2] );
"CHANINFO %s %s %s %s :%s", else IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s", Req->argv[0], Req->argv[1] );
Req->argv[0], Req->argv[1],
Req->argv[2], Req->argv[3],
Req->argv[4]);
else if (Req->argc == 3)
IRC_WriteStrServersPrefixFlag(Client, from, 'C',
"CHANINFO %s %s :%s",
Req->argv[0], Req->argv[1],
Req->argv[2]);
else
IRC_WriteStrServersPrefixFlag(Client, from, 'C',
"CHANINFO %s %s",
Req->argv[0], Req->argv[1]);
return CONNECTED; return CONNECTED;
} /* IRC_CHANINFO */ } /* IRC_CHANINFO */
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -48,11 +48,15 @@ IRC_CHARCONV(CLIENT *Client, REQUEST *Req)
assert (Client != NULL); assert (Client != NULL);
assert (Req != NULL); assert (Req != NULL);
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
strlcpy(encoding, Req->argv[0], sizeof(encoding)); strlcpy(encoding, Req->argv[0], sizeof(encoding));
ngt_UpperStr(encoding); ngt_UpperStr(encoding);
if (!Conn_SetEncoding(Client_Conn(Client), encoding)) if (!Conn_SetEncoding(Client_Conn(Client), encoding))
return IRC_WriteErrClient(Client, ERR_IP_CHARCONV_MSG, return IRC_WriteStrClient(Client, ERR_IP_CHARCONV_MSG,
Client_ID(Client), encoding); Client_ID(Client), encoding);
return IRC_WriteStrClient(Client, RPL_IP_CHARCONV_MSG, return IRC_WriteStrClient(Client, RPL_IP_CHARCONV_MSG,

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -33,21 +33,24 @@
#include "parse.h" #include "parse.h"
#include "irc.h" #include "irc.h"
#include "irc-info.h" #include "irc-info.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "exp.h" #include "exp.h"
#include "irc-login.h" #include "irc-login.h"
static void Kill_Nick PARAMS((char *Nick, char *Reason));
static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick, static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick,
bool InformClient)); bool InformClient));
/** /**
* Handler for the IRC "PASS" command. * Handler for the IRC "PASS" command.
* *
* @param Client The client from which this command has been received. * See RFC 2813 section 4.1.1, and RFC 2812 section 3.1.1.
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_PASS( CLIENT *Client, REQUEST *Req ) IRC_PASS( CLIENT *Client, REQUEST *Req )
@@ -60,7 +63,7 @@ IRC_PASS( CLIENT *Client, REQUEST *Req )
/* Return an error if this is not a local client */ /* Return an error if this is not a local client */
if (Client_Conn(Client) <= NONE) if (Client_Conn(Client) <= NONE)
return IRC_WriteErrClient(Client, ERR_UNKNOWNCOMMAND_MSG, return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
if (Client_Type(Client) == CLIENT_UNKNOWN && Req->argc == 1) { if (Client_Type(Client) == CLIENT_UNKNOWN && Req->argc == 1) {
@@ -80,12 +83,11 @@ IRC_PASS( CLIENT *Client, REQUEST *Req )
} else if (Client_Type(Client) == CLIENT_UNKNOWN || } else if (Client_Type(Client) == CLIENT_UNKNOWN ||
Client_Type(Client) == CLIENT_UNKNOWNSERVER) { Client_Type(Client) == CLIENT_UNKNOWNSERVER) {
/* Unregistered connection, but wrong number of arguments: */ /* Unregistered connection, but wrong number of arguments: */
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
} else { } else {
/* Registered connection, PASS command is not allowed! */ /* Registered connection, PASS command is not allowed! */
return IRC_WriteErrClient(Client, ERR_ALREADYREGISTRED_MSG, return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
Client_ID(Client)); Client_ID(Client));
} }
@@ -144,7 +146,7 @@ IRC_PASS( CLIENT *Client, REQUEST *Req )
} else } else
flags = ""; flags = "";
Log(LOG_INFO, Log(LOG_INFO,
"Peer on connection %d announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", "Peer on conenction %d announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").",
Client_Conn(Client), impl, serverver, Client_Conn(Client), impl, serverver,
protohigh, protolow, flags); protohigh, protolow, flags);
} else { } else {
@@ -165,12 +167,19 @@ IRC_PASS( CLIENT *Client, REQUEST *Req )
return CONNECTED; return CONNECTED;
} /* IRC_PASS */ } /* IRC_PASS */
/** /**
* Handler for the IRC "NICK" command. * Handler for the IRC "NICK" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.1.2 "Nick message", and RFC 2813, 4.1.3 "Nick".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * This function implements the IRC command "NICK" which is used to register
* with the server, to change already registered nicknames and to introduce
* new users which are connected to other servers.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_NICK( CLIENT *Client, REQUEST *Req ) IRC_NICK( CLIENT *Client, REQUEST *Req )
@@ -195,22 +204,31 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|| (Client_Type(Client) == CLIENT_SERVER && Req->argc == 1)) || (Client_Type(Client) == CLIENT_SERVER && Req->argc == 1))
{ {
/* User registration or change of nickname */ /* User registration or change of nickname */
_IRC_ARGC_EQ_OR_RETURN_(Client, Req, 1)
/* Wrong number of arguments? */
if( Req->argc != 1 )
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID( Client ),
Req->command );
/* Search "target" client */ /* Search "target" client */
if (Client_Type(Client) == CLIENT_SERVER) { if( Client_Type( Client ) == CLIENT_SERVER )
target = Client_Search(Req->prefix); {
if (!target) target = Client_Search( Req->prefix );
return IRC_WriteErrClient(Client, if( ! target )
ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient( Client,
Client_ID(Client), ERR_NOSUCHNICK_MSG,
Req->argv[0]); Client_ID( Client ),
} else { Req->argv[0] );
}
else
{
/* Is this a restricted client? */ /* Is this a restricted client? */
if (Client_HasMode(Client, 'r')) if( Client_HasMode( Client, 'r' ))
return IRC_WriteErrClient(Client, return IRC_WriteStrClient( Client,
ERR_RESTRICTED_MSG, ERR_RESTRICTED_MSG,
Client_ID(Client)); Client_ID( Client ));
target = Client; target = Client;
} }
@@ -219,14 +237,15 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
* do anything. This is how the original ircd behaves and some * do anything. This is how the original ircd behaves and some
* clients (for example Snak) expect it to be like this. * clients (for example Snak) expect it to be like this.
* But I doubt that this is "really the right thing" ... */ * But I doubt that this is "really the right thing" ... */
if (strcmp(Client_ID(target), Req->argv[0]) == 0) if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 )
return CONNECTED; return CONNECTED;
#endif #endif
/* Check that the new nickname is available. Special case: /* Check that the new nickname is available. Special case:
* the client only changes from/to upper to lower case. */ * the client only changes from/to upper to lower case. */
if (strcasecmp(Client_ID(target), Req->argv[0]) != 0) { if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
if (!Client_CheckNick(target, Req->argv[0])) {
if( ! Client_CheckNick( target, Req->argv[0] ))
return CONNECTED; return CONNECTED;
} }
@@ -242,11 +261,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
#ifndef STRICT_RFC #ifndef STRICT_RFC
if (Conf_AuthPing) { if (Conf_AuthPing) {
#ifdef HAVE_ARC4RANDOM
Conn_SetAuthPing(Client_Conn(Client), arc4random());
#else
Conn_SetAuthPing(Client_Conn(Client), rand()); Conn_SetAuthPing(Client_Conn(Client), rand());
#endif
IRC_WriteStrClient(Client, "PING :%ld", IRC_WriteStrClient(Client, "PING :%ld",
Conn_GetAuthPing(Client_Conn(Client))); Conn_GetAuthPing(Client_Conn(Client)));
LogDebug("Connection %d: sent AUTH PING %ld ...", LogDebug("Connection %d: sent AUTH PING %ld ...",
@@ -274,11 +289,9 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
/* Server or service introduces new client */ /* Server or service introduces new client */
/* Bad number of parameters? */ /* Bad number of parameters? */
if (Req->argc != 2 && Req->argc != 7) { if (Req->argc != 2 && Req->argc != 7)
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
}
if (Req->argc >= 7) { if (Req->argc >= 7) {
/* RFC 2813 compatible syntax */ /* RFC 2813 compatible syntax */
@@ -306,33 +319,28 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
* the new nick is already present on this server: * the new nick is already present on this server:
* the new and the old one have to be disconnected now. * the new and the old one have to be disconnected now.
*/ */
Log(LOG_ERR, Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
"Server %s introduces already registered nick \"%s\"!", Kill_Nick( Req->argv[0], "Nick collision" );
Client_ID(Client), Req->argv[0]); return CONNECTED;
return IRC_KillClient(Client, NULL, Req->argv[0],
"Nick collision");
} }
/* Find the Server this client is connected to */ /* Find the Server this client is connected to */
intr_c = Client_GetFromToken(Client, token); intr_c = Client_GetFromToken(Client, token);
if (!intr_c) { if( ! intr_c )
Log(LOG_ERR, {
"Server %s introduces nick \"%s\" on unknown server!?", Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
Client_ID(Client), Req->argv[0]); Kill_Nick( Req->argv[0], "Unknown server" );
return IRC_KillClient(Client, NULL, Req->argv[0], return CONNECTED;
"Unknown server");
} }
c = Client_NewRemoteUser(intr_c, nick, hops, user, hostname, c = Client_NewRemoteUser(intr_c, nick, hops, user, hostname,
token, modes, info, true); token, modes, info, true);
if (!c) { if( ! c )
/* Out of memory, we need to disconnect client to keep {
* network state consistent! */ /* out of memory, need to disconnect client to keep network state consistent */
Log(LOG_ALERT, Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
"Can't create client structure! (on connection %d)", Kill_Nick( Req->argv[0], "Server error" );
Client_Conn(Client)); return CONNECTED;
return IRC_KillClient(Client, NULL, Req->argv[0],
"Server error");
} }
/* RFC 2813: client is now fully registered, inform all the /* RFC 2813: client is now fully registered, inform all the
@@ -348,11 +356,10 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
return CONNECTED; return CONNECTED;
} }
else else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
return IRC_WriteErrClient(Client, ERR_ALREADYREGISTRED_MSG,
Client_ID(Client));
} /* IRC_NICK */ } /* IRC_NICK */
/** /**
* Handler for the IRC "SVSNICK" command. * Handler for the IRC "SVSNICK" command.
* *
@@ -368,6 +375,10 @@ IRC_SVSNICK(CLIENT *Client, REQUEST *Req)
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Search the originator */ /* Search the originator */
from = Client_Search(Req->prefix); from = Client_Search(Req->prefix);
if (!from) if (!from)
@@ -376,7 +387,7 @@ IRC_SVSNICK(CLIENT *Client, REQUEST *Req)
/* Search the target */ /* Search the target */
target = Client_Search(Req->argv[0]); target = Client_Search(Req->argv[0]);
if (!target || Client_Type(target) != CLIENT_USER) { if (!target || Client_Type(target) != CLIENT_USER) {
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
} }
@@ -400,9 +411,11 @@ IRC_SVSNICK(CLIENT *Client, REQUEST *Req)
/** /**
* Handler for the IRC "USER" command. * Handler for the IRC "USER" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.1.3 "User message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_USER(CLIENT * Client, REQUEST * Req) IRC_USER(CLIENT * Client, REQUEST * Req)
@@ -420,14 +433,18 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
Client_Type(Client) == CLIENT_GOTPASS) Client_Type(Client) == CLIENT_GOTPASS)
{ {
/* New connection */ /* New connection */
_IRC_ARGC_EQ_OR_RETURN_(Client, Req, 4) if (Req->argc != 4)
return IRC_WriteStrClient(Client,
ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
/* User name: only alphanumeric characters and limited /* User name: only alphanumeric characters and limited
punctuation is allowed.*/ punctuation is allowed.*/
ptr = Req->argv[0]; ptr = Req->argv[0];
while (*ptr) { while (*ptr) {
if (!isalnum((int)*ptr) && if (!isalnum((int)*ptr) &&
*ptr != '+' && *ptr != '-' && *ptr != '@' && *ptr != '+' && *ptr != '-' &&
*ptr != '.' && *ptr != '_') { *ptr != '.' && *ptr != '_') {
Conn_Close(Client_Conn(Client), NULL, Conn_Close(Client_Conn(Client), NULL,
"Invalid user name", true); "Invalid user name", true);
@@ -436,13 +453,6 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
ptr++; ptr++;
} }
/* Save the received username for authentication, and use
* it up to the first '@' as default user name (like ircd2.11,
* bahamut, ircd-seven, ...), prefixed with '~', if needed: */
Client_SetOrigUser(Client, Req->argv[0]);
ptr = strchr(Req->argv[0], '@');
if (ptr)
*ptr = '\0';
#ifdef IDENTAUTH #ifdef IDENTAUTH
ptr = Client_User(Client); ptr = Client_User(Client);
if (!ptr || !*ptr || *ptr == '~') if (!ptr || !*ptr || *ptr == '~')
@@ -450,6 +460,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
#else #else
Client_SetUser(Client, Req->argv[0], false); Client_SetUser(Client, Req->argv[0], false);
#endif #endif
Client_SetOrigUser(Client, Req->argv[0]);
/* "Real name" or user info text: Don't set it to the empty /* "Real name" or user info text: Don't set it to the empty
* string, the original ircd can't deal with such "real names" * string, the original ircd can't deal with such "real names"
@@ -470,11 +481,14 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
} else if (Client_Type(Client) == CLIENT_SERVER || } else if (Client_Type(Client) == CLIENT_SERVER ||
Client_Type(Client) == CLIENT_SERVICE) { Client_Type(Client) == CLIENT_SERVICE) {
/* Server/service updating an user */ /* Server/service updating an user */
_IRC_ARGC_EQ_OR_RETURN_(Client, Req, 4) if (Req->argc != 4)
return IRC_WriteStrClient(Client,
ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
c = Client_Search(Req->prefix); c = Client_Search(Req->prefix);
if (!c) if (!c)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Client_ID(Client),
Req->prefix); Req->prefix);
@@ -494,25 +508,29 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
return CONNECTED; return CONNECTED;
} else if (Client_Type(Client) == CLIENT_USER) { } else if (Client_Type(Client) == CLIENT_USER) {
/* Already registered connection */ /* Already registered connection */
return IRC_WriteErrClient(Client, ERR_ALREADYREGISTRED_MSG, return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
Client_ID(Client)); Client_ID(Client));
} else { } else {
/* Unexpected/invalid connection state? */ /* Unexpected/invalid connection state? */
return IRC_WriteErrClient(Client, ERR_NOTREGISTERED_MSG, return IRC_WriteStrClient(Client, ERR_NOTREGISTERED_MSG,
Client_ID(Client)); Client_ID(Client));
} }
} /* IRC_USER */ } /* IRC_USER */
/** /**
* Handler for the IRC "SERVICE" command. * Handler for the IRC "SERVICE" command.
* *
* This function implements IRC Services registration using the SERVICE command
* defined in RFC 2812 3.1.6 and RFC 2813 4.1.4.
*
* At the moment ngIRCd doesn't support directly linked services, so this * At the moment ngIRCd doesn't support directly linked services, so this
* function returns ERR_ERRONEUSNICKNAME when the SERVICE command has not been * function returns ERR_ERRONEUSNICKNAME when the SERVICE command has not been
* received from a peer server. * received from a peer server.
* *
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @returns CONNECTED or DISCONNECTED..
*/ */
GLOBAL bool GLOBAL bool
IRC_SERVICE(CLIENT *Client, REQUEST *Req) IRC_SERVICE(CLIENT *Client, REQUEST *Req)
@@ -526,13 +544,22 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
if (Client_Type(Client) != CLIENT_GOTPASS && if (Client_Type(Client) != CLIENT_GOTPASS &&
Client_Type(Client) != CLIENT_SERVER) Client_Type(Client) != CLIENT_SERVER)
return IRC_WriteErrClient(Client, ERR_ALREADYREGISTRED_MSG, return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
Client_ID(Client)); Client_ID(Client));
if (Req->argc != 6)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Client_Type(Client) != CLIENT_SERVER) if (Client_Type(Client) != CLIENT_SERVER)
return IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG, return IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
/* Bad number of parameters? */
if (Req->argc != 6)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
nick = Req->argv[0]; nick = Req->argv[0];
user = NULL; host = NULL; user = NULL; host = NULL;
token = atoi(Req->argv[1]); token = atoi(Req->argv[1]);
@@ -542,20 +569,20 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
/* Validate service name ("nickname") */ /* Validate service name ("nickname") */
c = Client_Search(nick); c = Client_Search(nick);
if(c) { if(c) {
/* Nickname collision: disconnect (KILL) both clients! */ /* Nickname collission: disconnect (KILL) both clients! */
Log(LOG_ERR, Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!",
"Server %s introduces already registered service \"%s\"!",
Client_ID(Client), nick); Client_ID(Client), nick);
return IRC_KillClient(Client, NULL, nick, "Nick collision"); Kill_Nick(nick, "Nick collision");
return CONNECTED;
} }
/* Get the server to which the service is connected */ /* Get the server to which the service is connected */
intr_c = Client_GetFromToken(Client, token); intr_c = Client_GetFromToken(Client, token);
if (! intr_c) { if (! intr_c) {
Log(LOG_ERR, Log(LOG_ERR, "Server %s introduces service \"%s\" on unknown server!?",
"Server %s introduces service \"%s\" on unknown server!?",
Client_ID(Client), nick); Client_ID(Client), nick);
return IRC_KillClient(Client, NULL, nick, "Unknown server"); Kill_Nick(nick, "Unknown server");
return CONNECTED;
} }
/* Get user and host name */ /* Get user and host name */
@@ -584,28 +611,37 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
if (! c) { if (! c) {
/* Couldn't create client structure, so KILL the service to /* Couldn't create client structure, so KILL the service to
* keep network status consistent ... */ * keep network status consistent ... */
Log(LOG_ALERT, Log(LOG_ALERT, "Can't create client structure! (on connection %d)",
"Can't create client structure! (on connection %d)",
Client_Conn(Client)); Client_Conn(Client));
return IRC_KillClient(Client, NULL, nick, "Server error"); Kill_Nick(nick, "Server error");
return CONNECTED;
} }
Client_Introduce(Client, c, CLIENT_SERVICE); Client_Introduce(Client, c, CLIENT_SERVICE);
return CONNECTED; return CONNECTED;
} /* IRC_SERVICE */ } /* IRC_SERVICE */
/** /**
* Handler for the IRC "WEBIRC" command. * Handler for the IRC "WEBIRC" command.
* *
* @param Client The client from which this command has been received. * See doc/Protocol.txt, section II.4:
* @param Req Request structure with prefix and all parameters. * "Update webchat/proxy client information".
* @return CONNECTED or DISCONNECTED. *
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_WEBIRC(CLIENT *Client, REQUEST *Req) IRC_WEBIRC(CLIENT *Client, REQUEST *Req)
{ {
/* Exactly 4 parameters are requited */
if (Req->argc != 4)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0) if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0)
return IRC_WriteErrClient(Client, ERR_PASSWDMISMATCH_MSG, return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
Client_ID(Client)); Client_ID(Client));
LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s", LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s",
@@ -614,27 +650,33 @@ IRC_WEBIRC(CLIENT *Client, REQUEST *Req)
Client_SetUser(Client, Req->argv[1], true); Client_SetUser(Client, Req->argv[1], true);
Client_SetOrigUser(Client, Req->argv[1]); Client_SetOrigUser(Client, Req->argv[1]);
Client_SetHostname(Client, Req->argv[2]); Client_SetHostname(Client, Req->argv[2]);
Client_SetIPAText(Client, Req->argv[3]);
return CONNECTED; return CONNECTED;
} /* IRC_WEBIRC */ } /* IRC_WEBIRC */
/** /**
* Handler for the IRC "QUIT" command. * Handler for the IRC "QUIT" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.1.7 "Quit", and RFC 2813, 4.1.5 "Quit".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_QUIT( CLIENT *Client, REQUEST *Req ) IRC_QUIT( CLIENT *Client, REQUEST *Req )
{ {
CLIENT *target; CLIENT *target;
char quitmsg[COMMAND_LEN]; char quitmsg[LINE_LEN];
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
/* Wrong number of arguments? */
if (Req->argc > 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Req->argc == 1) if (Req->argc == 1)
strlcpy(quitmsg, Req->argv[0], sizeof quitmsg); strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
@@ -649,11 +691,11 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
} }
if (target != Client) { if (target != Client) {
Client_Destroy(target, "Got QUIT command", Client_Destroy(target, "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true); Req->argc == 1 ? quitmsg : NULL, true);
return CONNECTED; return CONNECTED;
} else { } else {
Conn_Close(Client_Conn(Client), "Got QUIT command", Conn_Close(Client_Conn(Client), "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true); Req->argc == 1 ? quitmsg : NULL, true);
return DISCONNECTED; return DISCONNECTED;
} }
@@ -666,13 +708,14 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
} }
/* User, Service, or not yet registered */ /* User, Service, or not yet registered */
Conn_Close(Client_Conn(Client), "Got QUIT command", Conn_Close(Client_Conn(Client), "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true); Req->argc == 1 ? quitmsg : NULL, true);
return DISCONNECTED; return DISCONNECTED;
} }
} /* IRC_QUIT */ } /* IRC_QUIT */
#ifndef STRICT_RFC #ifndef STRICT_RFC
/** /**
@@ -681,9 +724,9 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
* We handle these commands here to avoid the quite long timeout when * We handle these commands here to avoid the quite long timeout when
* some user tries to access this IRC daemon using an web browser ... * some user tries to access this IRC daemon using an web browser ...
* *
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req ) IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req )
@@ -695,12 +738,15 @@ IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req )
#endif #endif
/** /**
* Handler for the IRC "PING" command. * Handler for the IRC "PING" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.7.2 "Ping message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_PING(CLIENT *Client, REQUEST *Req) IRC_PING(CLIENT *Client, REQUEST *Req)
@@ -711,11 +757,13 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
assert(Req != NULL); assert(Req != NULL);
if (Req->argc < 1) if (Req->argc < 1)
return IRC_WriteErrClient(Client, ERR_NOORIGIN_MSG, return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
Client_ID(Client)); Client_ID(Client));
#ifdef STRICT_RFC #ifdef STRICT_RFC
/* Don't ignore additional arguments when in "strict" mode */ /* Don't ignore additional arguments when in "strict" mode */
_IRC_ARGC_LE_OR_RETURN_(Client, Req, 2) if (Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
#endif #endif
if (Req->argc > 1) { if (Req->argc > 1) {
@@ -723,7 +771,7 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
target = Client_Search(Req->argv[1]); target = Client_Search(Req->argv[1]);
if (!target || Client_Type(target) != CLIENT_SERVER) if (!target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->argv[1]); Client_ID(Client), Req->argv[1]);
if (target != Client_ThisServer()) { if (target != Client_ThisServer()) {
@@ -733,7 +781,7 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
else else
from = Client; from = Client;
if (!from) if (!from)
return IRC_WriteErrClient(Client, return IRC_WriteStrClient(Client,
ERR_NOSUCHSERVER_MSG, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
@@ -751,7 +799,7 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
} else } else
from = Client_ThisServer(); from = Client_ThisServer();
if (!from) if (!from)
return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
Log(LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Log(LOG_DEBUG, "Connection %d: got PING, sending PONG ...",
@@ -768,12 +816,15 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
#endif #endif
} /* IRC_PING */ } /* IRC_PING */
/** /**
* Handler for the IRC "PONG" command. * Handler for the IRC "PONG" command.
* *
* @param Client The client from which this command has been received. * See RFC 2812, 3.7.3 "Pong message".
* @param Req Request structure with prefix and all parameters. *
* @return CONNECTED or DISCONNECTED. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_PONG(CLIENT *Client, REQUEST *Req) IRC_PONG(CLIENT *Client, REQUEST *Req)
@@ -791,20 +842,26 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
/* Wrong number of arguments? */ /* Wrong number of arguments? */
if (Req->argc < 1) { if (Req->argc < 1) {
if (Client_Type(Client) == CLIENT_USER) if (Client_Type(Client) == CLIENT_USER)
return IRC_WriteErrClient(Client, ERR_NOORIGIN_MSG, return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
Client_ID(Client)); Client_ID(Client));
else else
return CONNECTED; return CONNECTED;
} }
if (Client_Type(Client) == CLIENT_USER) { if (Req->argc > 2) {
_IRC_ARGC_LE_OR_RETURN_(Client, Req, 2) if (Client_Type(Client) == CLIENT_USER)
return IRC_WriteStrClient(Client,
ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
else
return CONNECTED;
} }
/* Forward? */ /* Forward? */
if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) { if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
target = Client_Search(Req->argv[0]); target = Client_Search(Req->argv[0]);
if (!target) if (!target)
return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
from = Client_Search(Req->prefix); from = Client_Search(Req->prefix);
@@ -812,7 +869,7 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
if (target != Client_ThisServer() && target != from) { if (target != Client_ThisServer() && target != from) {
/* Ok, we have to forward the message. */ /* Ok, we have to forward the message. */
if (!from) if (!from)
return IRC_WriteErrClient(Client, return IRC_WriteStrClient(Client,
ERR_NOSUCHSERVER_MSG, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
@@ -850,9 +907,8 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) { if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
Log(LOG_INFO, Log(LOG_INFO,
"Synchronization with \"%s\" done (connection %d): %ld second%s [%ld users, %ld channels].", "Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn), Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
time(NULL) - Conn_GetSignon(conn) == 1 ? "" : "s",
Client_UserCount(), Channel_CountVisible(NULL)); Client_UserCount(), Channel_CountVisible(NULL));
Conn_UpdatePing(conn); Conn_UpdatePing(conn);
} else } else
@@ -862,6 +918,33 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
return CONNECTED; return CONNECTED;
} /* IRC_PONG */ } /* IRC_PONG */
/**
* Kill all users with a specific nickname in the network.
*
* @param Nick Nickname.
* @param Reason Reason for the KILL.
*/
static void
Kill_Nick(char *Nick, char *Reason)
{
REQUEST r;
assert (Nick != NULL);
assert (Reason != NULL);
r.prefix = NULL;
r.argv[0] = Nick;
r.argv[1] = Reason;
r.argc = 2;
Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
Nick, Reason);
IRC_KILL(Client_ThisServer(), &r);
} /* Kill_Nick */
/** /**
* Change the nickname of a client. * Change the nickname of a client.
* *
@@ -901,4 +984,5 @@ Change_Nick(CLIENT *Origin, CLIENT *Target, char *NewNick, bool InformClient)
Client_SetID(Target, NewNick); Client_SetID(Target, NewNick);
} }
/* -eof- */ /* -eof- */

View File

@@ -1,113 +0,0 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
*
* 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.
* Please read the file COPYING, README and AUTHORS for more information.
*/
#ifndef __irc_macros_h__
#define __irc_macros_h__
/**
* @file
* Macros for functions that handle IRC commands.
*/
/**
* Make sure that number of passed parameters is equal to Count.
*
* If there are not exactly Count parameters, send an error to the client and
* return from the function.
*/
#define _IRC_ARGC_EQ_OR_RETURN_(Client, Req, Count) \
if (Req->argc != Count) { \
IRC_SetPenalty(Client, 2); \
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, \
Client_ID(Client), Req->command); \
}
/**
* Make sure that number of passed parameters is less or equal than Max.
*
* If there are more than Max parameters, send an error to the client and
* return from the function.
*/
#define _IRC_ARGC_LE_OR_RETURN_(Client, Req, Max) \
if (Req->argc > Max) { \
IRC_SetPenalty(Client, 2); \
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, \
Client_ID(Client), Req->command); \
}
/**
* Make sure that number of passed parameters is greater or equal than Min.
*
* If there aren't at least Min parameters, send an error to the client and
* return from the function.
*/
#define _IRC_ARGC_GE_OR_RETURN_(Client, Req, Min) \
if (Req->argc < Min) { \
IRC_SetPenalty(Client, 2); \
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, \
Client_ID(Client), Req->command); \
}
/**
* Make sure that number of passed parameters is in between Min and Max.
*
* If there aren't at least Min parameters or if there are more than Max
* parameters, send an error to the client and return from the function.
*/
#define _IRC_ARGC_BETWEEN_OR_RETURN_(Client, Req, Min, Max) \
if (Req->argc < Min || Req->argc > Max) { \
IRC_SetPenalty(Client, 2); \
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, \
Client_ID(Client), Req->command); \
}
/**
* Get sender of an IRC command.
*
* The sender is either stored in the prefix if the command has been
* received from a server or set to the client. If the sender is invalid,
* send an error to the client and return from the function.
*/
#define _IRC_GET_SENDER_OR_RETURN_(Sender, Req, Client) \
if (Client_Type(Client) == CLIENT_SERVER) \
Sender = Client_Search(Req->prefix); \
else \
Sender = Client; \
if (!Sender) \
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, \
Client_ID(Client), Req->prefix);
/**
* Get target of an IRC command and make sure that it is a server.
*
* Set the target to the local server if no target parameter is given in the
* received command, and send an error to the client and return from the
* function if the given target isn't resolvable to a server: the target
* parameter can be a server name, a nick name (then the target is set to
* the server to which this nick is connected), or a mask matching at least
* one server name in the network.
*/
#define _IRC_GET_TARGET_SERVER_OR_RETURN_(Target, Req, Argc, From) \
if (Req->argc > Argc) { \
Target = Client_Search(Req->argv[Argc]); \
if (!Target) \
Target = Client_SearchServer(Req->argv[Argc]); \
if (!Target) \
return IRC_WriteStrClient(From, ERR_NOSUCHSERVER_MSG, \
Client_ID(From), Req->argv[Argc]); \
if (Client_Type(Target) != CLIENT_SERVER) \
Target = Client_Introducer(Target); \
} else \
Target = Client_ThisServer();
#endif /* __irc_macros_h__ */
/* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -51,22 +51,26 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
if (Req->argc != 3)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
prefix = Client_Search(Req->prefix); prefix = Client_Search(Req->prefix);
if (!prefix) if (!prefix)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
target = Client_Search(Req->argv[0]); target = Client_Search(Req->argv[0]);
if (!target) if (!target)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
LogDebug("Got \"METADATA\" command from \"%s\" for client \"%s\": \"%s=%s\".", LogDebug("Got \"METADATA\" command from \"%s\" for client \"%s\": \"%s=%s\".",
Client_ID(prefix), Client_ID(target), Client_ID(prefix), Client_ID(target),
Req->argv[1], Req->argv[2]); Req->argv[1], Req->argv[2]);
/* Mark client: it has received a METADATA command */ /* Mark client: it has receiveda a METADATA command */
if (!Client_HasFlag(target, 'M')) { if (!strchr(Client_Flags(target), 'M')) {
snprintf(new_flags, sizeof new_flags, "%sM", snprintf(new_flags, sizeof new_flags, "%sM",
Client_Flags(target)); Client_Flags(target));
Client_SetFlags(target, new_flags); Client_SetFlags(target, new_flags);
@@ -92,10 +96,6 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
Client_SetInfo(target, Req->argv[2]); Client_SetInfo(target, Req->argv[2]);
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0) else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
Client_SetUser(target, Req->argv[2], true); Client_SetUser(target, Req->argv[2], true);
else if (strcasecmp(Req->argv[1], "accountname") == 0)
Client_SetAccountName(target, Req->argv[2]);
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "certfp") == 0)
Conn_SetCertFp(Client_Conn(target), Req->argv[2]);
else else
Log(LOG_WARNING, Log(LOG_WARNING,
"Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!", "Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!",

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@
#include "defines.h" #include "defines.h"
#include "conn.h" #include "conn.h"
#include "channel.h" #include "channel.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "lists.h" #include "lists.h"
#include "log.h" #include "log.h"
@@ -36,6 +35,7 @@
#include "exp.h" #include "exp.h"
#include "irc-mode.h" #include "irc-mode.h"
static bool Client_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin, static bool Client_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
CLIENT *Target)); CLIENT *Target));
static bool Channel_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin, static bool Channel_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
@@ -50,15 +50,16 @@ static bool Send_ListChange PARAMS((const bool IsAdd, const char ModeChar,
CLIENT *Prefix, CLIENT *Client, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Mask)); CHANNEL *Channel, const char *Mask));
/** /**
* Handler for the IRC "MODE" command. * Handler for the IRC "MODE" command.
* *
* This function detects whether user or channel modes should be modified * See RFC 2812 section 3.1.5 ("user mode message") and section 3.2.3
* and calls the appropriate sub-functions. * ("channel mode message"), and RFC 2811 section 4 ("channel modes").
* *
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_MODE( CLIENT *Client, REQUEST *Req ) IRC_MODE( CLIENT *Client, REQUEST *Req )
@@ -69,7 +70,20 @@ IRC_MODE( CLIENT *Client, REQUEST *Req )
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
_IRC_GET_SENDER_OR_RETURN_(origin, Req, Client) /* No parameters? */
if (Req->argc < 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Origin for answers */
if (Client_Type(Client) == CLIENT_SERVER) {
origin = Client_Search(Req->prefix);
if (!origin)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client),
Req->prefix);
} else
origin = Client;
/* Channel or user mode? */ /* Channel or user mode? */
cl = NULL; chan = NULL; cl = NULL; chan = NULL;
@@ -84,10 +98,11 @@ IRC_MODE( CLIENT *Client, REQUEST *Req )
return Channel_Mode(Client, Req, origin, chan); return Channel_Mode(Client, Req, origin, chan);
/* No target found! */ /* No target found! */
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
} /* IRC_MODE */ } /* IRC_MODE */
/** /**
* Check if the "mode limit" for a client has been reached. * Check if the "mode limit" for a client has been reached.
* *
@@ -108,14 +123,15 @@ Mode_Limit_Reached(CLIENT *Client, int Count)
return true; return true;
} }
/** /**
* Handle client mode requests * Handle client mode requests
* *
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @param Origin The originator of the MODE command (prefix). * @param Origin The originator of the MODE command (prefix).
* @param Target The target (client) of this MODE command. * @param Target The target (client) of this MODE command.
* @return CONNECTED or DISCONNECTED. * @returns CONNECTED or DISCONNECTED.
*/ */
static bool static bool
Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
@@ -130,7 +146,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
if (Client_Type(Client) == CLIENT_USER) { if (Client_Type(Client) == CLIENT_USER) {
/* Users are only allowed to manipulate their own modes! */ /* Users are only allowed to manipulate their own modes! */
if (Target != Client) if (Target != Client)
return IRC_WriteErrClient(Client, return IRC_WriteStrClient(Client,
ERR_USERSDONTMATCH_MSG, ERR_USERSDONTMATCH_MSG,
Client_ID(Client)); Client_ID(Client));
} }
@@ -152,7 +168,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
set = false; set = false;
strcpy(the_modes, "-"); strcpy(the_modes, "-");
} else } else
return IRC_WriteErrClient(Origin, ERR_UMODEUNKNOWNFLAG_MSG, return IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG_MSG,
Client_ID(Origin)); Client_ID(Origin));
x[1] = '\0'; x[1] = '\0';
@@ -211,34 +227,43 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
x[0] = 'a'; x[0] = 'a';
Client_SetAway(Origin, DEFAULT_AWAY_MSG); Client_SetAway(Origin, DEFAULT_AWAY_MSG);
} else } else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
case 'B': /* Bot */ case 'B': /* Bot */
if (Client_HasMode(Client, 'r')) if (Client_HasMode(Client, 'r'))
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_RESTRICTED_MSG, ERR_RESTRICTED_MSG,
Client_ID(Origin)); Client_ID(Origin));
else else
x[0] = 'B'; x[0] = 'B';
break; break;
case 'c': /* Receive connect notices */ case 'c': /* Receive connect notices
case 'q': /* KICK-protected user */ * (only settable by IRC operators!) */
/* (only settable by IRC operators!) */
if (!set || Client_Type(Client) == CLIENT_SERVER if (!set || Client_Type(Client) == CLIENT_SERVER
|| Client_HasMode(Origin, 'o')) || Client_OperByMe(Origin))
x[0] = *mode_ptr; x[0] = 'c';
else else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
case 'o': /* IRC operator (only unsettable!) */ case 'o': /* IRC operator (only unsettable!) */
if (!set || Client_Type(Client) == CLIENT_SERVER) { if (!set || Client_Type(Client) == CLIENT_SERVER) {
Client_SetOperByMe(Target, false);
x[0] = 'o'; x[0] = 'o';
} else } else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
break;
case 'q': /* KICK-protected user */
if (!set || Client_Type(Client) == CLIENT_SERVER
|| Client_OperByMe(Origin))
x[0] = 'q';
else
ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
@@ -246,7 +271,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
if (set || Client_Type(Client) == CLIENT_SERVER) if (set || Client_Type(Client) == CLIENT_SERVER)
x[0] = 'r'; x[0] = 'r';
else else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_RESTRICTED_MSG, ERR_RESTRICTED_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
@@ -254,22 +279,22 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
if (Client_Type(Client) == CLIENT_SERVER) if (Client_Type(Client) == CLIENT_SERVER)
x[0] = 'R'; x[0] = 'R';
else else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_NICKREGISTER_MSG, ERR_NICKREGISTER_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
case 'x': /* Cloak hostname */ case 'x': /* Cloak hostname */
if (Client_HasMode(Client, 'r')) if (Client_HasMode(Client, 'r'))
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_RESTRICTED_MSG, ERR_RESTRICTED_MSG,
Client_ID(Origin)); Client_ID(Origin));
else if (!set || Conf_CloakHostModeX[0] else if (!set || Conf_CloakHostModeX[0]
|| Client_Type(Client) == CLIENT_SERVER || Client_Type(Client) == CLIENT_SERVER
|| Client_HasMode(Origin, 'o')) { || Client_OperByMe(Client)) {
x[0] = 'x'; x[0] = 'x';
send_RPL_HOSTHIDDEN_MSG = true; send_RPL_HOSTHIDDEN_MSG = true;
} else } else
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
break; break;
@@ -279,7 +304,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
"Unknown mode \"%c%c\" from \"%s\"!?", "Unknown mode \"%c%c\" from \"%s\"!?",
set ? '+' : '-', *mode_ptr, set ? '+' : '-', *mode_ptr,
Client_ID(Origin)); Client_ID(Origin));
ok = IRC_WriteErrClient(Origin, ok = IRC_WriteStrClient(Origin,
ERR_UMODEUNKNOWNFLAG2_MSG, ERR_UMODEUNKNOWNFLAG2_MSG,
Client_ID(Origin), Client_ID(Origin),
set ? '+' : '-', set ? '+' : '-',
@@ -344,7 +369,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
} }
if (send_RPL_HOSTHIDDEN_MSG && Client_Conn(Target) > NONE) { if (send_RPL_HOSTHIDDEN_MSG && Client_Conn(Target) > NONE) {
/* A new (cloaked) hostname must be announced */ /* A new (cloaked) hostname must be annoucned */
IRC_WriteStrClientPrefix(Target, Origin, IRC_WriteStrClientPrefix(Target, Origin,
RPL_HOSTHIDDEN_MSG, RPL_HOSTHIDDEN_MSG,
Client_ID(Target), Client_ID(Target),
@@ -361,13 +386,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
return ok; return ok;
} /* Client_Mode */ } /* Client_Mode */
/*
* Reply to a channel mode request.
*
* @param Origin The originator of the MODE command (prefix).
* @param Channel The channel of which the modes should be sent.
* @return CONNECTED or DISCONNECTED.
*/
static bool static bool
Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel) Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel)
{ {
@@ -413,20 +432,15 @@ Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel)
return CONNECTED; return CONNECTED;
} }
/** /**
* Handle channel mode and channel-user mode changes * Handle channel mode and channel-user mode changes
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @param Origin The originator of the MODE command (prefix).
* @param Channel The target channel of this MODE command.
* @return CONNECTED or DISCONNECTED.
*/ */
static bool static bool
Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
{ {
char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2],
argadd[CLIENT_PASS_LEN], *mode_ptr; argadd[CLIENT_PASS_LEN], *mode_ptr, *o_mode_ptr;
bool connected, set, skiponce, retval, use_servermode, bool connected, set, skiponce, retval, use_servermode,
is_halfop, is_op, is_admin, is_owner, is_machine, is_oper; is_halfop, is_op, is_admin, is_owner, is_machine, is_oper;
int mode_arg, arg_arg, mode_arg_count = 0; int mode_arg, arg_arg, mode_arg_count = 0;
@@ -437,7 +451,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
is_halfop = is_op = is_admin = is_owner = is_machine = is_oper = false; is_halfop = is_op = is_admin = is_owner = is_machine = is_oper = false;
if (Channel_IsModeless(Channel)) if (Channel_IsModeless(Channel))
return IRC_WriteErrClient(Client, ERR_NOCHANMODES_MSG, return IRC_WriteStrClient(Client, ERR_NOCHANMODES_MSG,
Client_ID(Client), Channel_Name(Channel)); Client_ID(Client), Channel_Name(Channel));
/* Mode request: let's answer it :-) */ /* Mode request: let's answer it :-) */
@@ -446,7 +460,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
/* Check if origin is oper and opers can use mode */ /* Check if origin is oper and opers can use mode */
use_servermode = Conf_OperServerMode; use_servermode = Conf_OperServerMode;
if(Client_HasMode(Client, 'o') && Conf_OperCanMode) { if(Client_OperByMe(Client) && Conf_OperCanMode) {
is_oper = true; is_oper = true;
} }
@@ -458,7 +472,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
/* Check if client is member of channel or an oper or an server/service */ /* Check if client is member of channel or an oper or an server/service */
if(!Channel_IsMemberOf(Channel, Client) && !is_oper && !is_machine) if(!Channel_IsMemberOf(Channel, Client) && !is_oper && !is_machine)
return IRC_WriteErrClient(Origin, ERR_NOTONCHANNEL_MSG, return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -537,14 +551,18 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
arg_arg = -1; arg_arg = -1;
if(!is_machine && !is_oper) { if(!is_machine && !is_oper) {
if (Channel_UserHasMode(Channel, Client, 'q')) o_mode_ptr = Channel_UserModes(Channel, Client);
is_owner = true; while( *o_mode_ptr ) {
if (Channel_UserHasMode(Channel, Client, 'a')) if ( *o_mode_ptr == 'q')
is_admin = true; is_owner = true;
if (Channel_UserHasMode(Channel, Client, 'o')) if ( *o_mode_ptr == 'a')
is_op = true; is_admin = true;
if (Channel_UserHasMode(Channel, Client, 'h')) if ( *o_mode_ptr == 'o')
is_halfop = true; is_op = true;
if ( *o_mode_ptr == 'h')
is_halfop = true;
o_mode_ptr++;
}
} }
/* Validate modes */ /* Validate modes */
@@ -558,7 +576,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
case 'z': /* Secure connections only */ case 'z': /* Secure connections only */
if(!is_oper && !is_machine && !is_owner && if(!is_oper && !is_machine && !is_owner &&
!is_admin && !is_op) { !is_admin && !is_op) {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Channel_Name(Channel)); Client_ID(Origin), Channel_Name(Channel));
goto chan_exit; goto chan_exit;
@@ -574,7 +592,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
is_admin || is_op || is_halfop) is_admin || is_op || is_halfop)
x[0] = *mode_ptr; x[0] = *mode_ptr;
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Channel_Name(Channel)); Client_ID(Origin), Channel_Name(Channel));
break; break;
@@ -586,7 +604,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
is_admin || is_op || is_halfop) is_admin || is_op || is_halfop)
x[0] = *mode_ptr; x[0] = *mode_ptr;
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -602,7 +620,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
sizeof(argadd)); sizeof(argadd));
x[0] = *mode_ptr; x[0] = *mode_ptr;
} else { } else {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -613,8 +631,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
#ifdef STRICT_RFC #ifdef STRICT_RFC
/* Only send error message in "strict" mode, /* Only send error message in "strict" mode,
* this is how ircd2.11 and others behave ... */ * this is how ircd2.11 and others behave ... */
IRC_SetPenalty(Origin, 2); connected = IRC_WriteStrClient(Origin,
connected = IRC_WriteErrClient(Origin,
ERR_NEEDMOREPARAMS_MSG, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Origin), Req->command); Client_ID(Origin), Req->command);
#endif #endif
@@ -629,7 +646,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
is_admin || is_op || is_halfop) is_admin || is_op || is_halfop)
x[0] = *mode_ptr; x[0] = *mode_ptr;
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -647,7 +664,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
x[0] = *mode_ptr; x[0] = *mode_ptr;
} }
} else { } else {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -658,8 +675,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
#ifdef STRICT_RFC #ifdef STRICT_RFC
/* Only send error message in "strict" mode, /* Only send error message in "strict" mode,
* this is how ircd2.11 and others behave ... */ * this is how ircd2.11 and others behave ... */
IRC_SetPenalty(Origin, 2); connected = IRC_WriteStrClient(Origin,
connected = IRC_WriteErrClient(Origin,
ERR_NEEDMOREPARAMS_MSG, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Origin), Req->command); Client_ID(Origin), Req->command);
#endif #endif
@@ -673,14 +689,14 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
if(is_oper || is_machine) if(is_oper || is_machine)
x[0] = 'O'; x[0] = 'O';
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
} else if(is_oper || is_machine || is_owner || } else if(is_oper || is_machine || is_owner ||
is_admin || is_op) is_admin || is_op)
x[0] = 'O'; x[0] = 'O';
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -692,14 +708,14 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
if(is_oper || is_machine) if(is_oper || is_machine)
x[0] = 'P'; x[0] = 'P';
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG, ERR_NOPRIVILEGES_MSG,
Client_ID(Origin)); Client_ID(Origin));
} else if(is_oper || is_machine || is_owner || } else if(is_oper || is_machine || is_owner ||
is_admin || is_op) is_admin || is_op)
x[0] = 'P'; x[0] = 'P';
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -708,7 +724,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
case 'q': /* Owner */ case 'q': /* Owner */
case 'a': /* Channel admin */ case 'a': /* Channel admin */
if(!is_oper && !is_machine && !is_owner && !is_admin) { if(!is_oper && !is_machine && !is_owner && !is_admin) {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPPRIVTOOLOW_MSG, ERR_CHANOPPRIVTOOLOW_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -717,7 +733,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
case 'o': /* Channel operator */ case 'o': /* Channel operator */
if(!is_oper && !is_machine && !is_owner && if(!is_oper && !is_machine && !is_owner &&
!is_admin && !is_op) { !is_admin && !is_op) {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -726,7 +742,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
case 'h': /* Half Op */ case 'h': /* Half Op */
if(!is_oper && !is_machine && !is_owner && if(!is_oper && !is_machine && !is_owner &&
!is_admin && !is_op) { !is_admin && !is_op) {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -740,12 +756,12 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
if (client) if (client)
x[0] = *mode_ptr; x[0] = *mode_ptr;
else else
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_NOSUCHNICK_MSG, ERR_NOSUCHNICK_MSG,
Client_ID(Origin), Client_ID(Origin),
Req->argv[arg_arg]); Req->argv[arg_arg]);
} else { } else {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -760,8 +776,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
* mode, because most other servers don't do * mode, because most other servers don't do
* it as well and some clients send "wired" * it as well and some clients send "wired"
* MODE commands like "MODE #chan -ooo nick". */ * MODE commands like "MODE #chan -ooo nick". */
IRC_SetPenalty(Origin, 2); connected = IRC_WriteStrClient(Origin,
connected = IRC_WriteErrClient(Origin,
ERR_NEEDMOREPARAMS_MSG, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Origin), Req->command); Client_ID(Origin), Req->command);
#endif #endif
@@ -786,7 +801,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
Client, Channel, Client, Channel,
Req->argv[arg_arg]); Req->argv[arg_arg]);
} else { } else {
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Client_ID(Origin),
Channel_Name(Channel)); Channel_Name(Channel));
@@ -813,7 +828,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
"Unknown mode \"%c%c\" from \"%s\" on %s!?", "Unknown mode \"%c%c\" from \"%s\" on %s!?",
set ? '+' : '-', *mode_ptr, set ? '+' : '-', *mode_ptr,
Client_ID(Origin), Channel_Name(Channel)); Client_ID(Origin), Channel_Name(Channel));
connected = IRC_WriteErrClient(Origin, connected = IRC_WriteStrClient(Origin,
ERR_UNKNOWNMODE_MSG, ERR_UNKNOWNMODE_MSG,
Client_ID(Origin), *mode_ptr, Client_ID(Origin), *mode_ptr,
Channel_Name(Channel)); Channel_Name(Channel));
@@ -836,11 +851,12 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
/* Validate target client */ /* Validate target client */
if (client && (!Channel_IsMemberOf(Channel, client))) { if (client && (!Channel_IsMemberOf(Channel, client))) {
if (!IRC_WriteErrClient(Origin, ERR_USERNOTINCHANNEL_MSG, if (!IRC_WriteStrClient
Client_ID(Origin), (Origin, ERR_USERNOTINCHANNEL_MSG,
Client_ID(client), Client_ID(Origin), Client_ID(client),
Channel_Name(Channel))) Channel_Name(Channel)))
break; break;
continue; continue;
} }
@@ -925,35 +941,31 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
return connected; return connected;
} /* Channel_Mode */ } /* Channel_Mode */
/**
* Handler for the IRC "AWAY" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_AWAY( CLIENT *Client, REQUEST *Req ) IRC_AWAY( CLIENT *Client, REQUEST *Req )
{ {
assert (Client != NULL); assert( Client != NULL );
assert (Req != NULL); assert( Req != NULL );
if (Req->argc == 1 && Req->argv[0][0]) { if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
Client_SetAway(Client, Req->argv[0]);
Client_ModeAdd(Client, 'a'); if(( Req->argc == 1 ) && (Req->argv[0][0] ))
IRC_WriteStrServersPrefix(Client, Client, "MODE %s :+a", {
Client_ID( Client)); Client_SetAway( Client, Req->argv[0] );
return IRC_WriteStrClient(Client, RPL_NOWAWAY_MSG, Client_ModeAdd( Client, 'a' );
Client_ID( Client)); IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
} else { return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
Client_ModeDel(Client, 'a'); }
IRC_WriteStrServersPrefix(Client, Client, "MODE %s :-a", else
Client_ID( Client)); {
return IRC_WriteStrClient(Client, RPL_UNAWAY_MSG, Client_ModeDel( Client, 'a' );
Client_ID( Client)); IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
} }
} /* IRC_AWAY */ } /* IRC_AWAY */
/** /**
* Add entries to channel invite, ban and exception lists. * Add entries to channel invite, ban and exception lists.
* *
@@ -968,7 +980,7 @@ static bool
Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
const char *Pattern) const char *Pattern)
{ {
char mask[MASK_LEN]; const char *mask;
struct list_head *list = NULL; struct list_head *list = NULL;
long int current_count; long int current_count;
@@ -977,7 +989,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
assert(Pattern != NULL); assert(Pattern != NULL);
assert(what == 'I' || what == 'b' || what == 'e'); assert(what == 'I' || what == 'b' || what == 'e');
Lists_MakeMask(Pattern, mask, sizeof(mask)); mask = Lists_MakeMask(Pattern);
current_count = Lists_Count(Channel_GetListInvites(Channel)) current_count = Lists_Count(Channel_GetListInvites(Channel))
+ Lists_Count(Channel_GetListExcepts(Channel)) + Lists_Count(Channel_GetListExcepts(Channel))
+ Lists_Count(Channel_GetListBans(Channel)); + Lists_Count(Channel_GetListBans(Channel));
@@ -998,7 +1010,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
return CONNECTED; return CONNECTED;
if (Client_Type(Client) == CLIENT_USER && if (Client_Type(Client) == CLIENT_USER &&
current_count >= MAX_HNDL_CHANNEL_LISTS) current_count >= MAX_HNDL_CHANNEL_LISTS)
return IRC_WriteErrClient(Client, ERR_LISTFULL_MSG, return IRC_WriteStrClient(Client, ERR_LISTFULL_MSG,
Client_ID(Client), Client_ID(Client),
Channel_Name(Channel), mask, Channel_Name(Channel), mask,
MAX_HNDL_CHANNEL_LISTS); MAX_HNDL_CHANNEL_LISTS);
@@ -1020,8 +1032,9 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
return Send_ListChange(true, what, Prefix, Client, Channel, mask); return Send_ListChange(true, what, Prefix, Client, Channel, mask);
} }
/** /**
* Delete entries from channel invite, ban and exception lists. * Delete entries from channel invite, ban and exeption lists.
* *
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list. * @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
* @param Prefix The originator of the command. * @param Prefix The originator of the command.
@@ -1034,7 +1047,7 @@ static bool
Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
const char *Pattern) const char *Pattern)
{ {
char mask[MASK_LEN]; const char *mask;
struct list_head *list = NULL; struct list_head *list = NULL;
assert(Client != NULL); assert(Client != NULL);
@@ -1042,7 +1055,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
assert(Pattern != NULL); assert(Pattern != NULL);
assert(what == 'I' || what == 'b' || what == 'e'); assert(what == 'I' || what == 'b' || what == 'e');
Lists_MakeMask(Pattern, mask, sizeof(mask)); mask = Lists_MakeMask(Pattern);
switch (what) { switch (what) {
case 'I': case 'I':
@@ -1063,6 +1076,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
return Send_ListChange(false, what, Prefix, Client, Channel, mask); return Send_ListChange(false, what, Prefix, Client, Channel, mask);
} }
/** /**
* Send information about changed channel invite/ban/exception lists to clients. * Send information about changed channel invite/ban/exception lists to clients.
* *
@@ -1100,4 +1114,5 @@ Send_ListChange(const bool IsAdd, const char ModeChar, CLIENT *Prefix,
return ok; return ok;
} /* Send_ListChange */ } /* Send_ListChange */
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@
#include "defines.h" #include "defines.h"
#include "conn.h" #include "conn.h"
#include "channel.h" #include "channel.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "lists.h" #include "lists.h"
#include "log.h" #include "log.h"
@@ -34,7 +33,6 @@
#include "exp.h" #include "exp.h"
#include "irc-op.h" #include "irc-op.h"
/* Local functions */
static bool static bool
try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel, try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel,
@@ -43,22 +41,13 @@ try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel,
CLIENT *target = Client_Search(nick); CLIENT *target = Client_Search(nick);
if (!target) if (!target)
return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, Client_ID(from), nick);
Client_ID(from), nick);
Channel_Kick(peer, target, from, channel, reason); Channel_Kick(peer, target, from, channel, reason);
return true; return true;
} }
/* Global functions */
/**
* Handler for the IRC command "KICK".
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_KICK(CLIENT *Client, REQUEST *Req) IRC_KICK(CLIENT *Client, REQUEST *Req)
{ {
@@ -71,7 +60,9 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) if ((Req->argc < 2) || (Req->argc > 3))
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
while (*itemList) { while (*itemList) {
if (*itemList == ',') { if (*itemList == ',') {
@@ -90,6 +81,15 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
itemList++; itemList++;
} }
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
reason = Req->argc == 3 ? Req->argv[2] : Client_ID(from); reason = Req->argc == 3 ? Req->argv[2] : Client_ID(from);
currentNick = Req->argv[1]; currentNick = Req->argv[1];
currentChannel = Req->argv[0]; currentChannel = Req->argv[0];
@@ -122,20 +122,13 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
nickCount--; nickCount--;
} }
} else { } else {
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
} }
return true; return true;
} /* IRC_KICK */ } /* IRC_KICK */
/**
* Handler for the IRC command "INVITE".
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_INVITE(CLIENT *Client, REQUEST *Req) IRC_INVITE(CLIENT *Client, REQUEST *Req)
{ {
@@ -147,47 +140,51 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Search user */ /* Search user */
target = Client_Search(Req->argv[0]); target = Client_Search(Req->argv[0]);
if (!target || (Client_Type(target) != CLIENT_USER)) if (!target || (Client_Type(target) != CLIENT_USER))
return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
chan = Channel_Search(Req->argv[1]); chan = Channel_Search(Req->argv[1]);
if (chan) { if (chan) {
/* Channel exists. Is the user a valid member of the channel? */ /* Channel exists. Is the user a valid member of the channel? */
if (!Channel_IsMemberOf(chan, from)) if (!Channel_IsMemberOf(chan, from))
return IRC_WriteErrClient(from, ERR_NOTONCHANNEL_MSG, return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Req->argv[1]);
Client_ID(Client),
Req->argv[1]);
/* Is the channel "invite-disallow"? */ /* Is the channel "invite-disallow"? */
if (Channel_HasMode(chan, 'V')) if (strchr(Channel_Modes(chan), 'V'))
return IRC_WriteErrClient(from, ERR_NOINVITE_MSG, return IRC_WriteStrClient(from, ERR_NOINVITE_MSG,
Client_ID(from), Client_ID(from), Channel_Name(chan));
Channel_Name(chan));
/* Is the channel "invite-only"? */ /* Is the channel "invite-only"? */
if (Channel_HasMode(chan, 'i')) { if (strchr(Channel_Modes(chan), 'i')) {
/* Yes. The user must be channel owner/admin/operator/halfop! */ /* Yes. The user must be channel owner/admin/operator/halfop! */
if (!Channel_UserHasMode(chan, from, 'q') && if (!strchr(Channel_UserModes(chan, from), 'q') &&
!Channel_UserHasMode(chan, from, 'a') && !strchr(Channel_UserModes(chan, from), 'a') &&
!Channel_UserHasMode(chan, from, 'o') && !strchr(Channel_UserModes(chan, from), 'o') &&
!Channel_UserHasMode(chan, from, 'h')) !strchr(Channel_UserModes(chan, from), 'h'))
return IRC_WriteErrClient(from, return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG,
ERR_CHANOPRIVSNEEDED_MSG, Client_ID(from), Channel_Name(chan));
Client_ID(from),
Channel_Name(chan));
remember = true; remember = true;
} }
/* Is the target user already member of the channel? */ /* Is the target user already member of the channel? */
if (Channel_IsMemberOf(chan, target)) if (Channel_IsMemberOf(chan, target))
return IRC_WriteErrClient(from, ERR_USERONCHANNEL_MSG, return IRC_WriteStrClient(from, ERR_USERONCHANNEL_MSG,
Client_ID(from), Client_ID(from), Req->argv[0], Req->argv[1]);
Req->argv[0], Req->argv[1]);
/* If the target user is banned on that channel: remember invite */ /* If the target user is banned on that channel: remember invite */
if (Lists_Check(Channel_GetListBans(chan), target)) if (Lists_Check(Channel_GetListBans(chan), target))
@@ -200,8 +197,8 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
} }
} }
LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from), LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from), Req->argv[0], Req->argv[1]);
Req->argv[0], Req->argv[1]);
/* /*
* RFC 2812 says: * RFC 2812 says:
@@ -221,7 +218,7 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
Client_ID(from), Req->argv[0], colon_if_necessary, Req->argv[1])) Client_ID(from), Req->argv[0], colon_if_necessary, Req->argv[1]))
return DISCONNECTED; return DISCONNECTED;
if (Client_HasMode(target, 'a') && if (strchr(Client_Modes(target), 'a') &&
!IRC_WriteStrClient(from, RPL_AWAY_MSG, Client_ID(from), !IRC_WriteStrClient(from, RPL_AWAY_MSG, Client_ID(from),
Client_ID(target), Client_Away(target))) Client_ID(target), Client_Away(target)))
return DISCONNECTED; return DISCONNECTED;
@@ -229,4 +226,5 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
return CONNECTED; return CONNECTED;
} /* IRC_INVITE */ } /* IRC_INVITE */
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -28,14 +28,11 @@
#include "conf.h" #include "conf.h"
#include "channel.h" #include "channel.h"
#include "class.h" #include "class.h"
#include "parse.h"
#include "irc.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "lists.h"
#include "log.h" #include "log.h"
#include "match.h" #include "match.h"
#include "messages.h" #include "messages.h"
#include "parse.h"
#include "op.h" #include "op.h"
#include <exp.h> #include <exp.h>
@@ -50,13 +47,16 @@ Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
{ {
Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s", Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s",
Client_Mask(Client), errtoken, errmsg); Client_Mask(Client), errtoken, errmsg);
return IRC_WriteErrClient(Client, ERR_PASSWDMISMATCH_MSG, IRC_SetPenalty(Client, 3);
return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
Client_ID(Client)); Client_ID(Client));
} /* Bad_OperPass */ } /* Bad_OperPass */
/** /**
* Handler for the IRC "OPER" command. * Handler for the IRC "OPER" command.
* *
* See RFC 2812, 3.1.4 "Oper message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -70,6 +70,10 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
len = array_length(&Conf_Opers, sizeof(*op)); len = array_length(&Conf_Opers, sizeof(*op));
op = array_start(&Conf_Opers); op = array_start(&Conf_Opers);
for (i = 0; i < len && strcmp(op[i].name, Req->argv[0]); i++) for (i = 0; i < len && strcmp(op[i].name, Req->argv[0]); i++)
@@ -92,16 +96,20 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
Client_ID(Client)); Client_ID(Client));
} }
Log(LOG_NOTICE|LOG_snotice, if (!Client_OperByMe(Client))
"Got valid OPER for \"%s\" from \"%s\", user is an IRC operator now.", Log(LOG_NOTICE|LOG_snotice,
Req->argv[0], Client_Mask(Client)); "Got valid OPER from \"%s\", user is an IRC operator now.",
Client_Mask(Client));
Client_SetOperByMe(Client, true);
return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client)); return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client));
} /* IRC_OPER */ } /* IRC_OPER */
/** /**
* Handler for the IRC "DIE" command. * Handler for the IRC "DIE" command.
* *
* See RFC 2812, 4.3 "Die message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -120,6 +128,15 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
if (!Op_Check(Client, Req)) if (!Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
#ifdef STRICT_RFC
if (Req->argc != 0)
#else
if (Req->argc > 1)
#endif
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Is a message given? */ /* Is a message given? */
if (Req->argc > 0) { if (Req->argc > 0) {
c = Conn_First(); c = Conn_First();
@@ -142,6 +159,8 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
/** /**
* Handler for the IRC "REHASH" command. * Handler for the IRC "REHASH" command.
* *
* See RFC 2812, 4.2 "Rehash message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -157,6 +176,11 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
if (!Op_Check(Client, Req)) if (!Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 0)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command );
Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...",
Client_Mask(Client)); Client_Mask(Client));
IRC_WriteStrClient(Client, RPL_REHASHING_MSG, Client_ID(Client)); IRC_WriteStrClient(Client, RPL_REHASHING_MSG, Client_ID(Client));
@@ -169,6 +193,8 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
/** /**
* Handler for the IRC "RESTART" command. * Handler for the IRC "RESTART" command.
* *
* See RFC 2812, 4.4 "Restart message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -184,6 +210,11 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
if (!Op_Check(Client, Req)) if (!Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 0)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
Log(LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...", Log(LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...",
Client_Mask(Client)); Client_Mask(Client));
NGIRCd_SignalRestart = true; NGIRCd_SignalRestart = true;
@@ -194,6 +225,8 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
/** /**
* Handler for the IRC "CONNECT" command. * Handler for the IRC "CONNECT" command.
* *
* See RFC 2812, 3.4.7 "Connect message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -206,25 +239,21 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 2 && Req->argc != 3 &&
Req->argc != 5 && Req->argc != 6) {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
/* Invalid port number? */
if ((Req->argc > 1) && atoi(Req->argv[1]) < 1) {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
if (Client_Type(Client) != CLIENT_SERVER if (Client_Type(Client) != CLIENT_SERVER
&& !Client_HasMode(Client, 'o')) && !Client_HasMode(Client, 'o'))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 2 && Req->argc != 3 &&
Req->argc != 5 && Req->argc != 6)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Invalid port number? */
if ((Req->argc > 1) && atoi(Req->argv[1]) < 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
from = Client; from = Client;
target = Client_ThisServer(); target = Client_ThisServer();
@@ -233,14 +262,14 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) if (Client_Type(Client) == CLIENT_SERVER && Req->prefix)
from = Client_Search(Req->prefix); from = Client_Search(Req->prefix);
if (! from) if (! from)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
target = (Req->argc == 3) ? Client_Search(Req->argv[2]) target = (Req->argc == 3) ? Client_Search(Req->argv[2])
: Client_Search(Req->argv[5]); : Client_Search(Req->argv[5]);
if (! target || Client_Type(target) != CLIENT_SERVER) if (! target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Req->argv[0]); Client_ID(from), Req->argv[0]);
} }
if (target != Client_ThisServer()) { if (target != Client_ThisServer()) {
@@ -263,7 +292,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
switch (Req->argc) { switch (Req->argc) {
case 1: case 1:
if (!Conf_EnablePassiveServer(Req->argv[0])) if (!Conf_EnablePassiveServer(Req->argv[0]))
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Client_ID(from),
Req->argv[0]); Req->argv[0]);
break; break;
@@ -272,7 +301,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
/* Connect configured server */ /* Connect configured server */
if (!Conf_EnableServer if (!Conf_EnableServer
(Req->argv[0], (UINT16) atoi(Req->argv[1]))) (Req->argv[0], (UINT16) atoi(Req->argv[1])))
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Client_ID(from),
Req->argv[0]); Req->argv[0]);
break; break;
@@ -281,7 +310,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
if (!Conf_AddServer if (!Conf_AddServer
(Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2], (Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2],
Req->argv[3], Req->argv[4])) Req->argv[3], Req->argv[4]))
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Client_ID(from),
Req->argv[0]); Req->argv[0]);
} }
@@ -317,6 +346,11 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
if (!Op_Check(Client, Req)) if (!Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
IRC_SendWallops(Client_ThisServer(), Client_ThisServer(), IRC_SendWallops(Client_ThisServer(), Client_ThisServer(),
"Received DISCONNECT %s from %s", "Received DISCONNECT %s from %s",
Req->argv[0], Client_ID(Client)); Req->argv[0], Client_ID(Client));
@@ -330,7 +364,7 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
/* Disconnect configured server */ /* Disconnect configured server */
if (!Conf_DisableServer(Req->argv[0])) if (!Conf_DisableServer(Req->argv[0]))
return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->argv[0]); Client_ID(Client), Req->argv[0]);
/* Are we still connected or were we killed, too? */ /* Are we still connected or were we killed, too? */
@@ -343,6 +377,8 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
/** /**
* Handler for the IRC "WALLOPS" command. * Handler for the IRC "WALLOPS" command.
* *
* See RFC 2812, 4.7 "Operwall message".
*
* @param Client The client from which this command has been received. * @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @return CONNECTED or DISCONNECTED.
@@ -355,10 +391,15 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
switch (Client_Type(Client)) { switch (Client_Type(Client)) {
case CLIENT_USER: case CLIENT_USER:
if (!Op_Check(Client, Req)) if (!Client_OperByMe(Client))
return Op_NoPrivileges(Client, Req); return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
from = Client; from = Client;
break; break;
case CLIENT_SERVER: case CLIENT_SERVER:
@@ -369,7 +410,7 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
} }
if (!from) if (!from)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
IRC_SendWallops(Client, from, "%s", Req->argv[0]); IRC_SendWallops(Client, from, "%s", Req->argv[0]);
@@ -386,25 +427,22 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
GLOBAL bool GLOBAL bool
IRC_xLINE(CLIENT *Client, REQUEST *Req) IRC_xLINE(CLIENT *Client, REQUEST *Req)
{ {
CLIENT *from, *c, *c_next; CLIENT *from;
char reason[COMMAND_LEN], class_c;
struct list_head *list;
int class; int class;
char class_c;
assert(Client != NULL); assert(Client != NULL);
assert(Req != NULL); assert(Req != NULL);
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 3) {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
from = Op_Check(Client, Req); from = Op_Check(Client, Req);
if (!from) if (!from)
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 3)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
switch(Req->command[0]) { switch(Req->command[0]) {
case 'g': case 'g':
case 'G': case 'G':
@@ -449,20 +487,6 @@ IRC_xLINE(CLIENT *Client, REQUEST *Req)
Req->argv[0], Req->argv[1], Req->argv[0], Req->argv[1],
Req->argv[2]); Req->argv[2]);
} }
/* Check currently connected clients */
snprintf(reason, sizeof(reason), "%c-Line by \"%s\": \"%s\"",
class_c, Client_ID(from), Req->argv[2]);
list = Class_GetList(class);
c = Client_First();
while (c) {
c_next = Client_Next(c);
if ((class == CLASS_GLINE || Client_Conn(c) > NONE)
&& Lists_Check(list, c))
IRC_KillClient(Client, NULL,
Client_ID(c), reason);
c = c_next;
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "conn-zip.h" #include "conn-zip.h"
#include "conf.h" #include "conf.h"
#include "channel.h" #include "channel.h"
#include "irc-write.h"
#include "lists.h" #include "lists.h"
#include "log.h" #include "log.h"
#include "messages.h" #include "messages.h"
@@ -36,24 +37,20 @@
#include "numeric.h" #include "numeric.h"
#include "ngircd.h" #include "ngircd.h"
#include "irc-info.h" #include "irc-info.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "op.h" #include "op.h"
#include "exp.h" #include "exp.h"
#include "irc-server.h" #include "irc-server.h"
/** /**
* Handler for the IRC "SERVER" command. * Handler for the IRC command "SERVER".
* * See RFC 2813 section 4.1.2.
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_SERVER( CLIENT *Client, REQUEST *Req ) IRC_SERVER( CLIENT *Client, REQUEST *Req )
{ {
char str[100]; char str[LINE_LEN];
CLIENT *from, *c; CLIENT *from, *c;
int i; int i;
@@ -62,7 +59,7 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
/* Return an error if this is not a local client */ /* Return an error if this is not a local client */
if (Client_Conn(Client) <= NONE) if (Client_Conn(Client) <= NONE)
return IRC_WriteErrClient(Client, ERR_UNKNOWNCOMMAND_MSG, return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
if (Client_Type(Client) == CLIENT_GOTPASS || if (Client_Type(Client) == CLIENT_GOTPASS ||
@@ -72,19 +69,17 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
LogDebug("Connection %d: got SERVER command (new server link) ...", LogDebug("Connection %d: got SERVER command (new server link) ...",
Client_Conn(Client)); Client_Conn(Client));
if (Req->argc != 2 && Req->argc != 3) { if (Req->argc != 2 && Req->argc != 3)
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Client_ID(Client),
Req->command); Req->command);
}
/* Get configuration index of new remote server ... */ /* Get configuration index of new remote server ... */
for (i = 0; i < MAX_SERVERS; i++) for (i = 0; i < MAX_SERVERS; i++)
if (strcasecmp(Req->argv[0], Conf_Server[i].name) == 0) if (strcasecmp(Req->argv[0], Conf_Server[i].name) == 0)
break; break;
/* Make sure the remote server is configured here */ /* Makre sure the remote server is configured here */
if (i >= MAX_SERVERS) { if (i >= MAX_SERVERS) {
Log(LOG_ERR, Log(LOG_ERR,
"Connection %d: Server \"%s\" not configured here!", "Connection %d: Server \"%s\" not configured here!",
@@ -154,17 +149,17 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
Client_SetType(Client, CLIENT_UNKNOWNSERVER); Client_SetType(Client, CLIENT_UNKNOWNSERVER);
#ifdef ZLIB #ifdef ZLIB
if (Client_HasFlag(Client, 'Z') if (strchr(Client_Flags(Client), 'Z')
&& !Zip_InitConn(Client_Conn(Client))) { && !Zip_InitConn(Client_Conn(Client))) {
Conn_Close(Client_Conn(Client), Conn_Close(Client_Conn(Client),
"Can't initialize compression (zlib)!", "Can't inizialize compression (zlib)!",
NULL, false ); NULL, false );
return DISCONNECTED; return DISCONNECTED;
} }
#endif #endif
#ifdef IRCPLUS #ifdef IRCPLUS
if (Client_HasFlag(Client, 'H')) { if (strchr(Client_Flags(Client), 'H')) {
LogDebug("Peer supports IRC+ extended server handshake ..."); LogDebug("Peer supports IRC+ extended server handshake ...");
if (!IRC_Send_ISUPPORT(Client)) if (!IRC_Send_ISUPPORT(Client))
return DISCONNECTED; return DISCONNECTED;
@@ -185,70 +180,41 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
{ {
/* New server is being introduced to the network */ /* New server is being introduced to the network */
if (Req->argc != 4) { if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
/* check for existing server with same ID */ /* check for existing server with same ID */
if (!Client_CheckID(Client, Req->argv[0])) if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
return DISCONNECTED;
from = Client_Search( Req->prefix ); from = Client_Search( Req->prefix );
if (! from) { if( ! from )
{
/* Uh, Server, that introduced the new server is unknown?! */ /* Uh, Server, that introduced the new server is unknown?! */
Log(LOG_ALERT, Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
"Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", true);
Req->prefix, Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL,
"Unknown ID in prefix of SERVER", true);
return DISCONNECTED; return DISCONNECTED;
} }
c = Client_NewRemoteServer(Client, Req->argv[0], from, c = Client_NewRemoteServer(Client, Req->argv[0], from, atoi(Req->argv[1]), atoi(Req->argv[2]), Req->argv[3], true);
atoi(Req->argv[1]), atoi(Req->argv[2]),
Req->argv[3], true);
if (!c) { if (!c) {
Log(LOG_ALERT, Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
"Can't create client structure for server! (on connection %d)", Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", true);
Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL,
"Can't allocate client structure for remote server",
true);
return DISCONNECTED; return DISCONNECTED;
} }
if (Client_Hops(c) > 1 && Req->prefix[0]) if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) snprintf( str, sizeof( str ), "connected to %s, ", Client_ID( from ));
snprintf(str, sizeof(str), "connected to %s, ", else strcpy( str, "" );
Client_ID(from)); Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (via %s, %s%d hop%s).", Client_ID( c ), Client_ID( Client ), str, Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
else
strcpy(str, "");
Log(LOG_NOTICE|LOG_snotice,
"Server \"%s\" registered (via %s, %s%d hop%s).",
Client_ID(c), Client_ID(Client), str, Client_Hops(c),
Client_Hops(c) > 1 ? "s": "" );
/* notify other servers */ /* notify other servers */
IRC_WriteStrServersPrefix(Client, from, "SERVER %s %d %d :%s", IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
Client_ID(c), Client_Hops(c) + 1,
Client_MyToken(c), Client_Info(c));
return CONNECTED; return CONNECTED;
} else { } else
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
}
} /* IRC_SERVER */ } /* IRC_SERVER */
/*
* Handler for the IRC "NJOIN" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_NJOIN( CLIENT *Client, REQUEST *Req ) IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{ {
@@ -260,6 +226,8 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req )
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
strlcpy( nick_in, Req->argv[1], sizeof( nick_in )); strlcpy( nick_in, Req->argv[1], sizeof( nick_in ));
strcpy( nick_out, "" ); strcpy( nick_out, "" );
@@ -320,19 +288,15 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req )
} }
/* forward to other servers */ /* forward to other servers */
if (nick_out[0] != '\0') if( nick_out[0] != '\0' ) IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], nick_out );
IRC_WriteStrServersPrefix(Client, Client_ThisServer(),
"NJOIN %s :%s", Req->argv[0], nick_out);
return CONNECTED; return CONNECTED;
} /* IRC_NJOIN */ } /* IRC_NJOIN */
/** /**
* Handler for the IRC "SQUIT" command. * Handler for the IRC command "SQUIT".
* * See RFC 2813 section 4.1.2 and RFC 2812 section 3.1.8.
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_SQUIT(CLIENT * Client, REQUEST * Req) IRC_SQUIT(CLIENT * Client, REQUEST * Req)
@@ -349,6 +313,11 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
&& !Client_HasMode(Client, 'o')) && !Client_HasMode(Client, 'o'))
return Op_NoPrivileges(Client, Req); return Op_NoPrivileges(Client, Req);
/* Bad number of arguments? */
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) { if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) {
from = Client_Search(Req->prefix); from = Client_Search(Req->prefix);
if (Client_Type(from) != CLIENT_SERVER if (Client_Type(from) != CLIENT_SERVER
@@ -357,7 +326,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
} else } else
from = Client; from = Client;
if (!from) if (!from)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
if (Client_Type(Client) == CLIENT_USER) if (Client_Type(Client) == CLIENT_USER)
@@ -383,7 +352,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
if (Req->argv[1][0]) if (Req->argv[1][0])
if (Client_NextHop(from) != Client || con > NONE) if (Client_NextHop(from) != Client || con > NONE)
snprintf(msg, sizeof(msg), "\"%s\" (SQUIT from %s)", snprintf(msg, sizeof(msg), "%s (SQUIT from %s)",
Req->argv[1], Client_ID(from)); Req->argv[1], Client_ID(from));
else else
strlcpy(msg, Req->argv[1], sizeof(msg)); strlcpy(msg, Req->argv[1], sizeof(msg));
@@ -416,7 +385,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
logmsg[0] = '\0'; logmsg[0] = '\0';
if (!strchr(msg, '(')) if (!strchr(msg, '('))
snprintf(logmsg, sizeof(logmsg), snprintf(logmsg, sizeof(logmsg),
"\"%s\" (SQUIT from %s)", Req->argv[1], "%s (SQUIT from %s)", Req->argv[1],
Client_ID(from)); Client_ID(from));
Client_Destroy(target, logmsg[0] ? logmsg : msg, Client_Destroy(target, logmsg[0] ? logmsg : msg,
msg, false); msg, false);

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -33,58 +33,17 @@
#include "exp.h" #include "exp.h"
#include "irc-write.h" #include "irc-write.h"
#define SEND_TO_USER 1 #define SEND_TO_USER 1
#define SEND_TO_SERVER 2 #define SEND_TO_SERVER 2
static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client)); static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client, static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
CLIENT *Prefix, void *Buffer)); CLIENT *Prefix, void *Buffer));
static void Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer)); static bool Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer));
/**
* Send an error message to a client and enforce a penalty time.
*
* @param Client The target client.
* @param Format Format string.
* @return CONNECTED or DISCONNECTED.
*/
#ifdef PROTOTYPES
GLOBAL bool
IRC_WriteErrClient( CLIENT *Client, const char *Format, ... )
#else
GLOBAL bool
IRC_WriteErrClient( Client, Format, va_alist )
CLIENT *Client;
const char *Format;
va_dcl
#endif
{
char buffer[1000];
va_list ap;
assert(Client != NULL);
assert(Format != NULL);
#ifdef PROTOTYPES
va_start(ap, Format);
#else
va_start(ap);
#endif
vsnprintf(buffer, 1000, Format, ap);
va_end(ap);
IRC_SetPenalty(Client, 2);
return IRC_WriteStrClientPrefix(Client, Client_ThisServer(),
"%s", buffer);
}
/**
* Send a message to a client.
*
* @param Client The target client.
* @param Format Format string.
* @return CONNECTED or DISCONNECTED.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL bool GLOBAL bool
IRC_WriteStrClient( CLIENT *Client, const char *Format, ... ) IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
@@ -97,31 +56,27 @@ va_dcl
#endif #endif
{ {
char buffer[1000]; char buffer[1000];
bool ok = CONNECTED;
va_list ap; va_list ap;
assert(Client != NULL); assert( Client != NULL );
assert(Format != NULL); assert( Format != NULL );
#ifdef PROTOTYPES #ifdef PROTOTYPES
va_start(ap, Format); va_start( ap, Format );
#else #else
va_start(ap); va_start( ap );
#endif #endif
vsnprintf(buffer, 1000, Format, ap); vsnprintf( buffer, 1000, Format, ap );
va_end(ap); va_end( ap );
/* to the client itself */
ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
return ok;
} /* IRC_WriteStrClient */
return IRC_WriteStrClientPrefix(Client, Client_ThisServer(),
"%s", buffer);
}
/**
* Send a message to a client using a specific prefix.
*
* @param Client The target client.
* @param Prefix The prefix to use.
* @param Format Format string.
* @return CONNECTED or DISCONNECTED.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL bool GLOBAL bool
IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...) IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
@@ -153,24 +108,15 @@ va_dcl
return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s", return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s",
Get_Prefix(Client_NextHop(Client), Prefix), buffer); Get_Prefix(Client_NextHop(Client), Prefix), buffer);
} } /* IRC_WriteStrClientPrefix */
/**
* Send a message to all client in a channel.
*
* The message is only sent once per remote server.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Channel The target channel.
* @param Remote If not set, the message is sent to local clients only.
* @param Format Format string.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL bool
IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote, IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
const char *Format, ...) const char *Format, ...)
#else #else
GLOBAL void GLOBAL bool
IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist) IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
CLIENT *Client; CLIENT *Client;
CHANNEL *Chan; CHANNEL *Chan;
@@ -193,27 +139,21 @@ va_dcl
vsnprintf( buffer, 1000, Format, ap ); vsnprintf( buffer, 1000, Format, ap );
va_end( ap ); va_end( ap );
IRC_WriteStrChannelPrefix(Client, Chan, Client_ThisServer(), return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
Remote, "%s", buffer); } /* IRC_WriteStrChannel */
}
/** /**
* Send a message to all client in a channel using a specific prefix. * send message to all clients in the same channel, but only send message
* * once per remote server.
* The message is only sent once per remote server.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Channel The target channel.
* @param Prefix The prefix to use.
* @param Remote If not set, the message is sent to local clients only.
* @param Format Format string.
*/ */
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL bool
IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
bool Remote, const char *Format, ...) bool Remote, const char *Format, ...)
#else #else
GLOBAL void GLOBAL bool
IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist) IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
CLIENT *Client; CLIENT *Client;
CHANNEL *Chan; CHANNEL *Chan;
@@ -245,36 +185,29 @@ va_dcl
Conn_ClearFlags( ); Conn_ClearFlags( );
cl2chan = Channel_FirstMember( Chan ); cl2chan = Channel_FirstMember( Chan );
while(cl2chan) { while( cl2chan )
{
c = Channel_GetClient( cl2chan ); c = Channel_GetClient( cl2chan );
if (!Remote) { if( ! Remote )
if (Client_Conn(c) <= NONE) {
c = NULL; if( Client_Conn( c ) <= NONE ) c = NULL;
else if(Client_Type(c) == CLIENT_SERVER) else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
c = NULL;
} }
if(c) if( c ) c = Client_NextHop( c );
c = Client_NextHop(c);
if(c && c != Client) { if( c && ( c != Client ))
{
/* Ok, another Client */ /* Ok, another Client */
conn = Client_Conn(c); conn = Client_Conn( c );
if (Client_Type(c) == CLIENT_SERVER) if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
Conn_SetFlag(conn, SEND_TO_SERVER); else Conn_SetFlag( conn, SEND_TO_USER );
else
Conn_SetFlag(conn, SEND_TO_USER);
} }
cl2chan = Channel_NextMember(Chan, cl2chan); cl2chan = Channel_NextMember( Chan, cl2chan );
} }
Send_Marked_Connections(Prefix, buffer); return Send_Marked_Connections(Prefix, buffer);
} } /* IRC_WriteStrChannelPrefix */
/**
* Send a message to all the servers in the network.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Format Format string.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL void
IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...) IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
@@ -299,16 +232,10 @@ va_dcl
vsnprintf( buffer, 1000, Format, ap ); vsnprintf( buffer, 1000, Format, ap );
va_end( ap ); va_end( ap );
IRC_WriteStrServersPrefix(ExceptOf, Client_ThisServer(), "%s", buffer); IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
} } /* IRC_WriteStrServers */
/**
* Send a message to all the servers in the network using a specific prefix.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Prefix The prefix to use.
* @param Format Format string.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL void
IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix, IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
@@ -337,17 +264,9 @@ va_dcl
va_end( ap ); va_end( ap );
IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer ); IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
} } /* IRC_WriteStrServersPrefix */
/**
* Send a message to all the servers in the network using a specific prefix
* and matching a "client flag".
*
* @param Client The sending client, excluded while forwarding the message.
* @param Prefix The prefix to use.
* @param Flag Client flag that must be set on the target.
* @param Format Format string.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL void
IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag, IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
@@ -378,18 +297,9 @@ va_dcl
IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag, IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
cb_writeStrServersPrefixFlag, buffer); cb_writeStrServersPrefixFlag, buffer);
} } /* IRC_WriteStrServersPrefixFlag */
/**
* Send a message to all the servers in the network using a specific prefix
* and matching a "client flag" using a callback function.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Prefix The prefix to use.
* @param Flag Client flag that must be set on the target.
* @param callback Callback function.
* @param Format Format string.
*/
GLOBAL void GLOBAL void
IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag, IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data) void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
@@ -401,32 +311,24 @@ IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE && if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
c != Client_ThisServer() && c != ExceptOf) { c != Client_ThisServer() && c != ExceptOf) {
/* Found a target server, do the flags match? */ /* Found a target server, do the flags match? */
if (Flag == '\0' || Client_HasFlag(c, Flag)) if (Flag == '\0' || strchr(Client_Flags(c), Flag))
callback(c, Prefix, cb_data); callback(c, Prefix, cb_data);
} }
c = Client_Next(c); c = Client_Next(c);
} }
} } /* IRC_WriteStrServersPrefixFlag */
/** /**
* Send a message to all "related" clients. * send message to all clients that are in the same channels as the client sending this message.
* * only send message once per reote server.
* Related clients are the one that share one ore more channels with the client
* sending this message.
*
* The message is only sent once per remote server.
*
* @param Client The sending client, excluded while forwarding the message.
* @param Prefix The prefix to use.
* @param Remote If not set, the message is sent to local clients only.
* @param Format Format string.
*/ */
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL bool
IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote, IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
const char *Format, ...) const char *Format, ...)
#else #else
GLOBAL void GLOBAL bool
IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist) IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
CLIENT *Client; CLIENT *Client;
CLIENT *Prefix; CLIENT *Prefix;
@@ -482,16 +384,13 @@ va_dcl
chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan ); chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
} }
Send_Marked_Connections(Prefix, buffer); return Send_Marked_Connections(Prefix, buffer);
} /* IRC_WriteStrRelatedPrefix */ } /* IRC_WriteStrRelatedPrefix */
/** /**
* Send WALLOPS message. * Send WALLOPS message.
* */
* @param Client The sending client, excluded while forwarding the message.
* @param From The (remote) sender of the message.
* @param Format Format string.
*/
#ifdef PROTOTYPES #ifdef PROTOTYPES
GLOBAL void GLOBAL void
IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...) IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
@@ -535,32 +434,23 @@ va_dcl
} }
} /* IRC_SendWallops */ } /* IRC_SendWallops */
/**
* Set a "penalty time" for an IRC client.
*
* Note: penalty times are never set for server links or remote clients!
*
* @param Client The client.
* @param Seconds The additional "penalty time" to enforce.
*/
GLOBAL void GLOBAL void
IRC_SetPenalty(CLIENT *Client, time_t Seconds) IRC_SetPenalty( CLIENT *Client, time_t Seconds )
{ {
CONN_ID c; CONN_ID c;
assert(Client != NULL); assert( Client != NULL );
assert(Seconds > 0); assert( Seconds > 0 );
if (Client_Type(Client) == CLIENT_SERVER) if( Client_Type( Client ) == CLIENT_SERVER ) return;
return;
c = Client_Conn(Client); c = Client_Conn( Client );
if (c <= NONE) if (c > NONE)
return; Conn_SetPenalty(c, Seconds);
Conn_SetPenalty(c, Seconds);
} /* IRC_SetPenalty */ } /* IRC_SetPenalty */
static const char * static const char *
Get_Prefix(CLIENT *Target, CLIENT *Client) Get_Prefix(CLIENT *Target, CLIENT *Client)
{ {
@@ -573,22 +463,19 @@ Get_Prefix(CLIENT *Target, CLIENT *Client)
return Client_MaskCloaked(Client); return Client_MaskCloaked(Client);
} /* Get_Prefix */ } /* Get_Prefix */
static void static void
cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer) cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
{ {
IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer); IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
} /* cb_writeStrServersPrefixFlag */ } /* cb_writeStrServersPrefixFlag */
/**
* Send a message to all marked connections using a specific prefix. static bool
*
* @param Prefix The prefix to use.
* @param Buffer The message to send.
*/
static void
Send_Marked_Connections(CLIENT *Prefix, const char *Buffer) Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
{ {
CONN_ID conn; CONN_ID conn;
bool ok = CONNECTED;
assert(Prefix != NULL); assert(Prefix != NULL);
assert(Buffer != NULL); assert(Buffer != NULL);
@@ -596,13 +483,17 @@ Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
conn = Conn_First(); conn = Conn_First();
while (conn != NONE) { while (conn != NONE) {
if (Conn_Flag(conn) == SEND_TO_SERVER) if (Conn_Flag(conn) == SEND_TO_SERVER)
Conn_WriteStr(conn, ":%s %s", ok = Conn_WriteStr(conn, ":%s %s",
Client_ID(Prefix), Buffer); Client_ID(Prefix), Buffer);
else if (Conn_Flag(conn) == SEND_TO_USER) else if (Conn_Flag(conn) == SEND_TO_USER)
Conn_WriteStr(conn, ":%s %s", ok = Conn_WriteStr(conn, ":%s %s",
Client_MaskCloaked(Prefix), Buffer); Client_MaskCloaked(Prefix), Buffer);
conn = Conn_Next(conn); if (!ok)
break;
conn = Conn_Next( conn );
} }
return ok;
} }
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -17,15 +17,13 @@
* Sending IRC commands over the network (header) * Sending IRC commands over the network (header)
*/ */
GLOBAL bool IRC_WriteErrClient PARAMS((CLIENT *Client, const char *Format, ...));
GLOBAL bool IRC_WriteStrClient PARAMS((CLIENT *Client, const char *Format, ...)); GLOBAL bool IRC_WriteStrClient PARAMS((CLIENT *Client, const char *Format, ...));
GLOBAL bool IRC_WriteStrClientPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, GLOBAL bool IRC_WriteStrClientPrefix PARAMS((CLIENT *Client, CLIENT *Prefix,
const char *Format, ...)); const char *Format, ...));
GLOBAL void IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan, GLOBAL bool IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan,
bool Remote, const char *Format, ...)); bool Remote, const char *Format, ...));
GLOBAL void IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan, GLOBAL bool IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan,
CLIENT *Prefix, bool Remote, const char *Format, ...)); CLIENT *Prefix, bool Remote, const char *Format, ...));
GLOBAL void IRC_WriteStrServers PARAMS((CLIENT *ExceptOf, GLOBAL void IRC_WriteStrServers PARAMS((CLIENT *ExceptOf,
@@ -38,7 +36,7 @@ GLOBAL void IRC_WriteStrServersPrefixFlag_CB PARAMS((CLIENT *ExceptOf,
CLIENT *Prefix, char Flag, CLIENT *Prefix, char Flag,
void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)); void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data));
GLOBAL void IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, GLOBAL bool IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix,
bool Remote, const char *Format, ...)); bool Remote, const char *Format, ...));
GLOBAL void IRC_SendWallops PARAMS((CLIENT *Client, CLIENT *From, GLOBAL void IRC_SendWallops PARAMS((CLIENT *Client, CLIENT *From,

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -27,25 +27,24 @@
#include "channel.h" #include "channel.h"
#include "conn-encoding.h" #include "conn-encoding.h"
#include "defines.h" #include "defines.h"
#include "irc-macros.h"
#include "irc-write.h" #include "irc-write.h"
#include "log.h" #include "log.h"
#include "match.h" #include "match.h"
#include "messages.h" #include "messages.h"
#include "parse.h" #include "parse.h"
#include "op.h"
#include "tool.h" #include "tool.h"
#include "exp.h" #include "exp.h"
#include "irc.h" #include "irc.h"
static char *Option_String PARAMS((CONN_ID Idx)); static char *Option_String PARAMS((CONN_ID Idx));
static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType, static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType,
bool SendErrors)); bool SendErrors));
static bool Send_Message_Mask PARAMS((CLIENT *from, char *command, static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
char *targetMask, char *message, char *targetMask, char *message,
bool SendErrors)); bool SendErrors));
static bool Help PARAMS((CLIENT *Client, const char *Topic));
/** /**
* Check if a list limit is reached and inform client accordingly. * Check if a list limit is reached and inform client accordingly.
@@ -75,15 +74,9 @@ IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit,
return true; return true;
} }
/**
* Handler for the IRC "ERROR" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_ERROR(CLIENT *Client, REQUEST *Req) IRC_ERROR( CLIENT *Client, REQUEST *Req )
{ {
assert( Client != NULL ); assert( Client != NULL );
assert( Req != NULL ); assert( Req != NULL );
@@ -109,10 +102,11 @@ IRC_ERROR(CLIENT *Client, REQUEST *Req)
return CONNECTED; return CONNECTED;
} /* IRC_ERROR */ } /* IRC_ERROR */
/** /**
* Handler for the IRC "KILL" command. * Handler for the IRC "KILL" command.
* *
* This function implements the IRC command "KILL" which is used to selectively * This function implements the IRC command "KILL" wich is used to selectively
* disconnect clients. It can be used by IRC operators and servers, for example * disconnect clients. It can be used by IRC operators and servers, for example
* to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1. * to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1.
* *
@@ -120,22 +114,28 @@ IRC_ERROR(CLIENT *Client, REQUEST *Req)
* KILL command being received over the network! Client is Client_ThisServer() * KILL command being received over the network! Client is Client_ThisServer()
* in this case, and the prefix in Req is NULL. * in this case, and the prefix in Req is NULL.
* *
* @param Client The client from which this command has been received or * @param Client The client from which this command has been received
* Client_ThisServer() when generated interanlly. * or Client_ThisServer() when generated interanlly.
* @param Req Request structure with prefix and all parameters. * @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED. * @returns CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_KILL(CLIENT *Client, REQUEST *Req) IRC_KILL( CLIENT *Client, REQUEST *Req )
{ {
CLIENT *prefix; CLIENT *prefix, *c;
char reason[COMMAND_LEN]; char reason[COMMAND_LEN], *msg;
CONN_ID my_conn, conn;
assert (Client != NULL); assert (Client != NULL);
assert (Req != NULL); assert (Req != NULL);
if (Client_Type(Client) != CLIENT_SERVER && !Op_Check(Client, Req)) if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
return Op_NoPrivileges(Client, Req); return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Get prefix (origin); use the client if no prefix is given. */ /* Get prefix (origin); use the client if no prefix is given. */
if (Req->prefix) if (Req->prefix)
@@ -144,8 +144,7 @@ IRC_KILL(CLIENT *Client, REQUEST *Req)
prefix = Client; prefix = Client;
/* Log a warning message and use this server as origin when the /* Log a warning message and use this server as origin when the
* prefix (origin) is invalid. And this is the reason why we don't * prefix (origin) is invalid. */
* use the _IRC_GET_SENDER_OR_RETURN_ macro above! */
if (!prefix) { if (!prefix) {
Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
Req->prefix ); Req->prefix );
@@ -154,7 +153,7 @@ IRC_KILL(CLIENT *Client, REQUEST *Req)
if (Client != Client_ThisServer()) if (Client != Client_ThisServer())
Log(LOG_NOTICE|LOG_snotice, Log(LOG_NOTICE|LOG_snotice,
"Got KILL command from \"%s\" for \"%s\": \"%s\".", "Got KILL command from \"%s\" for \"%s\": %s",
Client_Mask(prefix), Req->argv[0], Req->argv[1]); Client_Mask(prefix), Req->argv[0], Req->argv[1]);
/* Build reason string: Prefix the "reason" if the originator is a /* Build reason string: Prefix the "reason" if the originator is a
@@ -165,28 +164,74 @@ IRC_KILL(CLIENT *Client, REQUEST *Req)
else else
strlcpy(reason, Req->argv[1], sizeof(reason)); strlcpy(reason, Req->argv[1], sizeof(reason));
return IRC_KillClient(Client, prefix, Req->argv[0], reason); /* Inform other servers */
} IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
Req->argv[0], reason);
/* Save ID of this connection */
my_conn = Client_Conn( Client );
/* Do we host such a client? */
c = Client_Search( Req->argv[0] );
if( c )
{
if(( Client_Type( c ) != CLIENT_USER ) &&
( Client_Type( c ) != CLIENT_GOTNICK ))
{
/* Target of this KILL is not a regular user, this is
* invalid! So we ignore this case if we received a
* regular KILL from the network and try to kill the
* client/connection anyway (but log an error!) if the
* origin is the local server. */
if( Client != Client_ThisServer( ))
{
/* Invalid KILL received from remote */
if( Client_Type( c ) == CLIENT_SERVER )
msg = ERR_CANTKILLSERVER_MSG;
else
msg = ERR_NOPRIVILEGES_MSG;
return IRC_WriteStrClient( Client, msg,
Client_ID( Client ));
}
Log( LOG_ERR, "Got KILL for invalid client type: %d, \"%s\"!",
Client_Type( c ), Req->argv[0] );
}
/* Kill the client NOW:
* - Close the local connection (if there is one),
* - Destroy the CLIENT structure for remote clients.
* Note: Conn_Close() removes the CLIENT structure as well. */
conn = Client_Conn( c );
if(conn > NONE)
Conn_Close(conn, NULL, reason, true);
else
Client_Destroy(c, NULL, reason, false);
}
else
Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] );
/* Are we still connected or were we killed, too? */
if(( my_conn > NONE ) && ( Conn_GetClient( my_conn )))
return CONNECTED;
else
return DISCONNECTED;
} /* IRC_KILL */
/** /**
* Handler for the IRC "NOTICE" command. * Handler for the IRC command NOTICE.
* */
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_NOTICE(CLIENT *Client, REQUEST *Req) IRC_NOTICE(CLIENT *Client, REQUEST *Req)
{ {
return Send_Message(Client, Req, CLIENT_USER, false); return Send_Message(Client, Req, CLIENT_USER, false);
} /* IRC_NOTICE */ } /* IRC_NOTICE */
/** /**
* Handler for the IRC "PRIVMSG" command. * Handler for the IRC command PRIVMSG.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_PRIVMSG(CLIENT *Client, REQUEST *Req) IRC_PRIVMSG(CLIENT *Client, REQUEST *Req)
@@ -194,12 +239,9 @@ IRC_PRIVMSG(CLIENT *Client, REQUEST *Req)
return Send_Message(Client, Req, CLIENT_USER, true); return Send_Message(Client, Req, CLIENT_USER, true);
} /* IRC_PRIVMSG */ } /* IRC_PRIVMSG */
/** /**
* Handler for the IRC "SQUERY" command. * Handler for the IRC command SQUERY.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/ */
GLOBAL bool GLOBAL bool
IRC_SQUERY(CLIENT *Client, REQUEST *Req) IRC_SQUERY(CLIENT *Client, REQUEST *Req)
@@ -207,269 +249,95 @@ IRC_SQUERY(CLIENT *Client, REQUEST *Req)
return Send_Message(Client, Req, CLIENT_SERVICE, true); return Send_Message(Client, Req, CLIENT_SERVICE, true);
} /* IRC_SQUERY */ } /* IRC_SQUERY */
/*
* Handler for the IRC "TRACE" command. GLOBAL bool
* IRC_TRACE( CLIENT *Client, REQUEST *Req )
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_TRACE(CLIENT *Client, REQUEST *Req)
{ {
CLIENT *from, *target, *c; CLIENT *from, *target, *c;
CONN_ID idx, idx2; CONN_ID idx, idx2;
char user[CLIENT_USER_LEN]; char user[CLIENT_USER_LEN];
assert(Client != NULL); assert( Client != NULL );
assert(Req != NULL); assert( Req != NULL );
IRC_SetPenalty(Client, 3); /* Bad number of arguments? */
if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client) /* Search sender */
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from) if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
else from = Client;
if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Search target */
if( Req->argc == 1 ) target = Client_Search( Req->argv[0] );
else target = Client_ThisServer( );
/* Forward command to other server? */ /* Forward command to other server? */
if (target != Client_ThisServer()) { if( target != Client_ThisServer( ))
/* Send RPL_TRACELINK back to initiator */ {
idx = Client_Conn(Client); if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
assert(idx > NONE);
idx2 = Client_Conn(Client_NextHop(target));
assert(idx2 > NONE);
if (!IRC_WriteStrClient(from, RPL_TRACELINK_MSG, /* Send RPL_TRACELINK back to initiator */
Client_ID(from), PACKAGE_NAME, idx = Client_Conn( Client ); assert( idx > NONE );
PACKAGE_VERSION, Client_ID(target), idx2 = Client_Conn( Client_NextHop( target )); assert( idx2 > NONE );
Client_ID(Client_NextHop(target)), if( ! IRC_WriteStrClient( from, RPL_TRACELINK_MSG, Client_ID( from ), PACKAGE_NAME, PACKAGE_VERSION, Client_ID( target ), Client_ID( Client_NextHop( target )), Option_String( idx2 ), time( NULL ) - Conn_StartTime( idx2 ), Conn_SendQ( idx ), Conn_SendQ( idx2 ))) return DISCONNECTED;
Option_String(idx2),
time(NULL) - Conn_StartTime(idx2),
Conn_SendQ(idx), Conn_SendQ(idx2)))
return DISCONNECTED;
/* Forward command */ /* Forward command */
IRC_WriteStrClientPrefix(target, from, "TRACE %s", Req->argv[0]); IRC_WriteStrClientPrefix( target, from, "TRACE %s", Req->argv[0] );
return CONNECTED; return CONNECTED;
} }
/* Infos about all connected servers */ /* Infos about all connected servers */
c = Client_First(); c = Client_First( );
while (c) { while( c )
if (Client_Conn(c) > NONE) { {
if( Client_Conn( c ) > NONE )
{
/* Local client */ /* Local client */
if (Client_Type(c) == CLIENT_SERVER) { if( Client_Type( c ) == CLIENT_SERVER )
{
/* Server link */ /* Server link */
strlcpy(user, Client_User(c), sizeof(user)); strlcpy( user, Client_User( c ), sizeof( user ));
if (user[0] == '~') if( user[0] == '~' ) strlcpy( user, "unknown", sizeof( user ));
strlcpy(user, "unknown", sizeof(user)); if( ! IRC_WriteStrClient( from, RPL_TRACESERVER_MSG, Client_ID( from ), Client_ID( c ), user, Client_Hostname( c ), Client_Mask( Client_ThisServer( )), Option_String( Client_Conn( c )))) return DISCONNECTED;
if (!IRC_WriteStrClient(from,
RPL_TRACESERVER_MSG,
Client_ID(from), Client_ID(c),
user, Client_Hostname(c),
Client_Mask(Client_ThisServer()),
Option_String(Client_Conn(c))))
return DISCONNECTED;
} }
if (Client_Type(c) == CLIENT_USER if(( Client_Type( c ) == CLIENT_USER ) && ( strchr( Client_Modes( c ), 'o' )))
&& Client_HasMode(c, 'o')) { {
/* IRC Operator */ /* IRC Operator */
if (!IRC_WriteStrClient(from, if( ! IRC_WriteStrClient( from, RPL_TRACEOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
RPL_TRACEOPERATOR_MSG,
Client_ID(from), Client_ID(c)))
return DISCONNECTED;
} }
} }
c = Client_Next( c ); c = Client_Next( c );
} }
return IRC_WriteStrClient(from, RPL_TRACEEND_MSG, Client_ID(from), IRC_SetPenalty( Client, 3 );
Conf_ServerName, PACKAGE_NAME, return IRC_WriteStrClient( from, RPL_TRACEEND_MSG, Client_ID( from ), Conf_ServerName, PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel );
PACKAGE_VERSION, NGIRCd_DebugLevel);
} /* IRC_TRACE */ } /* IRC_TRACE */
/**
* Handler for the IRC "HELP" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool GLOBAL bool
IRC_HELP(CLIENT *Client, REQUEST *Req) IRC_HELP( CLIENT *Client, REQUEST *Req )
{ {
COMMAND *cmd; COMMAND *cmd;
assert(Client != NULL); assert( Client != NULL );
assert(Req != NULL); assert( Req != NULL );
IRC_SetPenalty(Client, 2); /* Bad number of arguments? */
if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0) cmd = Parse_GetCommandStruct( );
|| (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) { while( cmd->name )
/* Help text available and requested */ {
if (Req->argc >= 1) if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
return Help(Client, Req->argv[0]);
if (!Help(Client, "Intro"))
return DISCONNECTED;
return CONNECTED;
}
cmd = Parse_GetCommandStruct();
while(cmd->name) {
if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
Client_ID(Client), cmd->name))
return DISCONNECTED;
cmd++; cmd++;
} }
IRC_SetPenalty( Client, 2 );
return CONNECTED; return CONNECTED;
} /* IRC_HELP */ } /* IRC_HELP */
/**
* Kill an client identified by its nick name.
*
* Please note that after killig a client, its CLIENT cond CONNECTION
* structures are invalid. So the caller must make sure on its own not to
* access data of probably killed clients after calling this function!
*
* @param Client The client from which the command leading to the KILL has
* been received, or NULL. The KILL will no be forwarded in this
* direction. Only relevant when From is set, too.
* @param From The client from which the command originated, or NULL for
the local server.
* @param Nick The nick name to kill.
* @param Reason Text to send as reason to the client and other servers.
*/
GLOBAL bool
IRC_KillClient(CLIENT *Client, CLIENT *From, const char *Nick, const char *Reason)
{
const char *msg;
CONN_ID my_conn, conn;
CLIENT *c;
/* Do we know such a client in the network? */
c = Client_Search(Nick);
if (!c) {
LogDebug("Client with nick \"%s\" is unknown, not forwaring.", Nick);
return CONNECTED;
}
/* Inform other servers */
IRC_WriteStrServersPrefix(From ? Client : NULL,
From ? From : Client_ThisServer(),
"KILL %s :%s", Nick, Reason);
if (Client_Type(c) != CLIENT_USER && Client_Type(c) != CLIENT_GOTNICK) {
/* Target of this KILL is not a regular user, this is
* invalid! So we ignore this case if we received a
* regular KILL from the network and try to kill the
* client/connection anyway (but log an error!) if the
* origin is the local server. */
if (Client != Client_ThisServer()) {
/* Invalid KILL received from remote */
if (Client_Type(c) == CLIENT_SERVER)
msg = ERR_CANTKILLSERVER_MSG;
else
msg = ERR_NOPRIVILEGES_MSG;
return IRC_WriteErrClient(Client, msg, Client_ID(Client));
}
Log(LOG_ERR,
"Got KILL for invalid client type: %d, \"%s\"!",
Client_Type(c), Nick);
}
/* Save ID of this connection */
my_conn = Client_Conn(Client);
/* Kill the client NOW:
* - Close the local connection (if there is one),
* - Destroy the CLIENT structure for remote clients.
* Note: Conn_Close() removes the CLIENT structure as well. */
conn = Client_Conn(c);
if(conn > NONE)
Conn_Close(conn, NULL, Reason, true);
else
Client_Destroy(c, NULL, Reason, false);
/* Are we still connected or were we killed, too? */
if (my_conn > NONE && Conn_GetClient(my_conn))
return CONNECTED;
else
return DISCONNECTED;
}
/**
* Send help for a given topic to the client.
*
* @param Client The client requesting help.
* @param Topoc The help topic requested.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Help(CLIENT *Client, const char *Topic)
{
char *line;
size_t helptext_len, len_str, idx_start, lines = 0;
bool in_article = false;
assert(Client != NULL);
assert(Topic != NULL);
helptext_len = array_bytes(&Conf_Helptext);
line = array_start(&Conf_Helptext);
while (helptext_len > 0) {
len_str = strlen(line) + 1;
assert(helptext_len >= len_str);
helptext_len -= len_str;
if (in_article) {
/* The first character in each article text line must
* be a TAB (ASCII 9) character which will be stripped
* in the output. If it is not a TAB, the end of the
* article has been reached. */
if (line[0] != '\t') {
if (lines > 0)
return CONNECTED;
else
break;
}
/* A single '.' character indicates an empty line */
if (line[1] == '.' && line[2] == '\0')
idx_start = 2;
else
idx_start = 1;
if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
Client_ID(Client),
&line[idx_start]))
return DISCONNECTED;
lines++;
} else {
if (line[0] == '-' && line[1] == ' '
&& strcasecmp(&line[2], Topic) == 0)
in_article = true;
}
line += len_str;
}
/* Help topic not found (or empty)! */
if (!IRC_WriteStrClient(Client, "NOTICE %s :No help for \"%s\" found!",
Client_ID(Client), Topic))
return DISCONNECTED;
return CONNECTED;
}
/**
* Get pointer to a static string representing the connection "options".
*
* @param Idx Connection index.
* @return Pointer to static (global) string buffer.
*/
static char * static char *
#ifdef ZLIB #ifdef ZLIB
Option_String(CONN_ID Idx) Option_String(CONN_ID Idx)
@@ -480,26 +348,21 @@ Option_String(UNUSED CONN_ID Idx)
static char option_txt[8]; static char option_txt[8];
#ifdef ZLIB #ifdef ZLIB
UINT16 options; UINT16 options;
#endif
assert(Idx != NONE);
options = Conn_Options(Idx); options = Conn_Options(Idx);
#endif
strcpy(option_txt, "F"); /* No idea what this means, but the strcpy(option_txt, "F"); /* No idea what this means, but the
* original ircd sends it ... */ * original ircd sends it ... */
#ifdef SSL_SUPPORT
if(options & CONN_SSL) /* SSL encrypted link */
strlcat(option_txt, "s", sizeof(option_txt));
#endif
#ifdef ZLIB #ifdef ZLIB
if(options & CONN_ZIP) /* zlib compression enabled */ if(options & CONN_ZIP) /* zlib compression supported. */
strlcat(option_txt, "z", sizeof(option_txt)); strcat(option_txt, "z");
#endif #endif
LogDebug(" *** %d: %d = %s", Idx, options, option_txt);
return option_txt; return option_txt;
} /* Option_String */ } /* Option_String */
static bool static bool
Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
{ {
@@ -516,20 +379,19 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
if (Req->argc == 0) { if (Req->argc == 0) {
if (!SendErrors) if (!SendErrors)
return CONNECTED; return CONNECTED;
return IRC_WriteErrClient(Client, ERR_NORECIPIENT_MSG, return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
} }
if (Req->argc == 1) { if (Req->argc == 1) {
if (!SendErrors) if (!SendErrors)
return CONNECTED; return CONNECTED;
return IRC_WriteErrClient(Client, ERR_NOTEXTTOSEND_MSG, return IRC_WriteStrClient(Client, ERR_NOTEXTTOSEND_MSG,
Client_ID(Client)); Client_ID(Client));
} }
if (Req->argc > 2) { if (Req->argc > 2) {
if (!SendErrors) if (!SendErrors)
return CONNECTED; return CONNECTED;
IRC_SetPenalty(Client, 2); return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command); Client_ID(Client), Req->command);
} }
@@ -538,7 +400,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
else else
from = Client; from = Client;
if (!from) if (!from)
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix); Client_ID(Client), Req->prefix);
#ifdef ICONV #ifdef ICONV
@@ -633,7 +495,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
#else #else
if (Client_Type(cl) != ForceType) { if (Client_Type(cl) != ForceType) {
#endif #endif
if (SendErrors && !IRC_WriteErrClient( if (SendErrors && !IRC_WriteStrClient(
from, ERR_NOSUCHNICK_MSG,Client_ID(from), from, ERR_NOSUCHNICK_MSG,Client_ID(from),
currentTarget)) currentTarget))
return DISCONNECTED; return DISCONNECTED;
@@ -654,7 +516,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
!Client_HasMode(from, 'o') && !Client_HasMode(from, 'o') &&
!(Client_Type(from) == CLIENT_SERVER) && !(Client_Type(from) == CLIENT_SERVER) &&
!(Client_Type(from) == CLIENT_SERVICE)) { !(Client_Type(from) == CLIENT_SERVICE)) {
if (SendErrors && !IRC_WriteErrClient(from, if (SendErrors && !IRC_WriteStrClient(from,
ERR_NONONREG_MSG, ERR_NONONREG_MSG,
Client_ID(from), Client_ID(cl))) Client_ID(from), Client_ID(cl)))
return DISCONNECTED; return DISCONNECTED;
@@ -670,7 +532,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
cl2chan = Channel_NextChannelOf(cl, cl2chan); cl2chan = Channel_NextChannelOf(cl, cl2chan);
} }
if (!cl2chan) { if (!cl2chan) {
if (SendErrors && !IRC_WriteErrClient( if (SendErrors && !IRC_WriteStrClient(
from, ERR_NOTONSAMECHANNEL_MSG, from, ERR_NOTONSAMECHANNEL_MSG,
Client_ID(from), Client_ID(cl))) Client_ID(from), Client_ID(cl)))
return DISCONNECTED; return DISCONNECTED;
@@ -679,7 +541,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
} }
if (SendErrors && (Client_Type(Client) != CLIENT_SERVER) if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
&& Client_HasMode(cl, 'a')) { && strchr(Client_Modes(cl), 'a')) {
/* Target is away */ /* Target is away */
if (!IRC_WriteStrClient(from, RPL_AWAY_MSG, if (!IRC_WriteStrClient(from, RPL_AWAY_MSG,
Client_ID(from), Client_ID(from),
@@ -710,7 +572,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
} else { } else {
if (!SendErrors) if (!SendErrors)
return CONNECTED; return CONNECTED;
if (!IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG, if (!IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(from), currentTarget)) Client_ID(from), currentTarget))
return DISCONNECTED; return DISCONNECTED;
} }
@@ -724,6 +586,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
return CONNECTED; return CONNECTED;
} /* Send_Message */ } /* Send_Message */
static bool static bool
Send_Message_Mask(CLIENT * from, char * command, char * targetMask, Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
char * message, bool SendErrors) char * message, bool SendErrors)
@@ -735,10 +598,10 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
cl = NULL; cl = NULL;
if (!Client_HasMode(from, 'o')) { if (strchr(Client_Modes(from), 'o') == NULL) {
if (!SendErrors) if (!SendErrors)
return true; return true;
return IRC_WriteErrClient(from, ERR_NOPRIVILEGES_MSG, return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from)); Client_ID(from));
} }
@@ -753,7 +616,7 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
{ {
if (!SendErrors) if (!SendErrors)
return true; return true;
return IRC_WriteErrClient(from, ERR_WILDTOPLEVEL, targetMask); return IRC_WriteStrClient(from, ERR_WILDTOPLEVEL, targetMask);
} }
/* #: hostmask, see RFC 2812, sec. 3.3.1 */ /* #: hostmask, see RFC 2812, sec. 3.3.1 */
@@ -783,4 +646,5 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
return CONNECTED; return CONNECTED;
} /* Send_Message_Mask */ } /* Send_Message_Mask */
/* -eof- */ /* -eof- */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -28,9 +28,6 @@ GLOBAL bool IRC_SQUERY PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_TRACE PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_TRACE PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_HELP PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_HELP PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_KillClient PARAMS((CLIENT *Client, CLIENT *From,
const char *Nick, const char *Reason));
#endif #endif
/* -eof- */ /* -eof- */

View File

@@ -34,6 +34,8 @@
#include "exp.h" #include "exp.h"
#include "lists.h" #include "lists.h"
#define MASK_LEN (2*CLIENT_HOST_LEN)
struct list_elem { struct list_elem {
struct list_elem *next; /** pointer to next list element */ struct list_elem *next; /** pointer to next list element */
char mask[MASK_LEN]; /** IRC mask */ char mask[MASK_LEN]; /** IRC mask */
@@ -128,8 +130,7 @@ Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
if (e) { if (e) {
e->valid_until = ValidUntil; e->valid_until = ValidUntil;
if (Reason) { if (Reason) {
if (e->reason) free(e->reason);
free(e->reason);
e->reason = strdup(Reason); e->reason = strdup(Reason);
} }
return true; return true;
@@ -260,13 +261,17 @@ Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
/** /**
* Generate a valid IRC mask from "any" string given. * Generate a valid IRC mask from "any" string given.
* *
* Attention: This mask is only valid until the next call to Lists_MakeMask(),
* because a single global buffer ist used! You have to copy the generated
* mask to some sane location yourself!
*
* @param Pattern Source string to generate an IRC mask for. * @param Pattern Source string to generate an IRC mask for.
* @param mask Buffer to store the mask. * @return Pointer to global result buffer.
* @param len Size of the buffer.
*/ */
GLOBAL void GLOBAL const char *
Lists_MakeMask(const char *Pattern, char *mask, size_t len) Lists_MakeMask(const char *Pattern)
{ {
static char TheMask[MASK_LEN];
char *excl, *at; char *excl, *at;
assert(Pattern != NULL); assert(Pattern != NULL);
@@ -279,22 +284,30 @@ Lists_MakeMask(const char *Pattern, char *mask, size_t len)
if (!at && !excl) { if (!at && !excl) {
/* Neither "!" nor "@" found: use string as nickname */ /* Neither "!" nor "@" found: use string as nickname */
strlcpy(mask, Pattern, len - 5); strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
strlcat(mask, "!*@*", len); strlcat(TheMask, "!*@*", sizeof(TheMask));
} else if (!at && excl) { return TheMask;
}
if (!at && excl) {
/* Domain part is missing */ /* Domain part is missing */
strlcpy(mask, Pattern, len - 3); strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
strlcat(mask, "@*", len); strlcat(TheMask, "@*", sizeof(TheMask));
} else if (at && !excl) { return TheMask;
}
if (at && !excl) {
/* User name is missing */ /* User name is missing */
*at = '\0'; at++; *at = '\0'; at++;
strlcpy(mask, Pattern, len - 5); strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
strlcat(mask, "!*@", len); strlcat(TheMask, "!*@", sizeof(TheMask));
strlcat(mask, at, len); strlcat(TheMask, at, sizeof(TheMask));
} else { return TheMask;
/* All parts (nick, user and domain name) are given */
strlcpy(mask, Pattern, len);
} }
/* All parts (nick, user and domain name) are given */
strlcpy(TheMask, Pattern, sizeof(TheMask));
return TheMask;
} /* Lists_MakeMask */ } /* Lists_MakeMask */
/** /**
@@ -307,20 +320,18 @@ Lists_MakeMask(const char *Pattern, char *mask, size_t len)
bool bool
Lists_Check(struct list_head *h, CLIENT *Client) Lists_Check(struct list_head *h, CLIENT *Client)
{ {
return Lists_CheckReason(h, Client, NULL, 0); return Lists_CheckReason(h, Client) != NULL;
} }
/** /**
* Check if a client is listed in a list and store the reason. * Check if a client is listed in a list and return the "reason".
* *
* @param h List head. * @param h List head.
* @param Client Client to check. * @param Client Client to check.
* @param reason Buffer to store the reason.
* @param len Size of the buffer if reason should be saved.
* @return true if client is listed, false if not. * @return true if client is listed, false if not.
*/ */
bool char *
Lists_CheckReason(struct list_head *h, CLIENT *Client, char *reason, size_t len) Lists_CheckReason(struct list_head *h, CLIENT *Client)
{ {
struct list_elem *e, *last, *next; struct list_elem *e, *last, *next;
@@ -331,22 +342,20 @@ Lists_CheckReason(struct list_head *h, CLIENT *Client, char *reason, size_t len)
while (e) { while (e) {
next = e->next; next = e->next;
if (Match(e->mask, Client_MaskCloaked(Client))) { if (Match(e->mask, Client_Mask(Client))) {
if (len && e->reason)
strlcpy(reason, e->reason, len);
if (e->valid_until == 1) { if (e->valid_until == 1) {
/* Entry is valid only once, delete it */ /* Entry is valid only once, delete it */
LogDebug("Deleted \"%s\" from list (used).", LogDebug("Deleted \"%s\" from list (used).",
e->mask); e->mask);
Lists_Unlink(h, last, e); Lists_Unlink(h, last, e);
} }
return true; return e->reason ? e->reason : "";
} }
last = e; last = e;
e = next; e = next;
} }
return false; return NULL;
} }
/** /**

View File

@@ -30,8 +30,7 @@ GLOBAL struct list_elem *Lists_GetFirst PARAMS((const struct list_head *));
GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *)); GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *));
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client)); GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client));
GLOBAL bool Lists_CheckReason PARAMS((struct list_head *head, CLIENT *client, GLOBAL char *Lists_CheckReason PARAMS((struct list_head *head, CLIENT *client));
char *reason, size_t len));
GLOBAL struct list_elem *Lists_CheckDupeMask PARAMS((const struct list_head *head, GLOBAL struct list_elem *Lists_CheckDupeMask PARAMS((const struct list_head *head,
const char *mask)); const char *mask));
@@ -42,7 +41,7 @@ GLOBAL unsigned long Lists_Count PARAMS((struct list_head *h));
GLOBAL void Lists_Free PARAMS((struct list_head *head)); GLOBAL void Lists_Free PARAMS((struct list_head *head));
GLOBAL void Lists_MakeMask PARAMS((const char *Pattern, char *mask, size_t len)); GLOBAL const char *Lists_MakeMask PARAMS((const char *Pattern));
GLOBAL const char *Lists_GetMask PARAMS((const struct list_elem *e)); GLOBAL const char *Lists_GetMask PARAMS((const struct list_elem *e));
GLOBAL const char *Lists_GetReason PARAMS((const struct list_elem *e)); GLOBAL const char *Lists_GetReason PARAMS((const struct list_elem *e));
GLOBAL time_t Lists_GetValidity PARAMS((const struct list_elem *e)); GLOBAL time_t Lists_GetValidity PARAMS((const struct list_elem *e));

View File

@@ -53,7 +53,7 @@ Log_Message(int Level, const char *msg)
if (!Is_Daemon) { if (!Is_Daemon) {
/* log to console */ /* log to console */
fprintf(stdout, "[%ld:%d %4ld] %s\n", (long)getpid(), Level, fprintf(stdout, "[%ld:%d %4ld] %s\n", (long)getpid(), Level,
(long)(time(NULL) - NGIRCd_Start), msg); (long)time(NULL) - NGIRCd_Start, msg);
fflush(stdout); fflush(stdout);
} }
#ifdef SYSLOG #ifdef SYSLOG
@@ -109,9 +109,8 @@ Log_ReInit(void)
GLOBAL void GLOBAL void
Log_Exit( void ) Log_Exit( void )
{ {
Log(LOG_INFO, "%s done%s, served %lu connection%s.", PACKAGE_NAME, Log(LOG_NOTICE, "%s done%s, served %lu connections.", PACKAGE_NAME,
NGIRCd_SignalRestart ? " (restarting)" : "", Conn_CountAccepted(), NGIRCd_SignalRestart ? " (restarting)" : "", Conn_CountAccepted());
Conn_CountAccepted() == 1 ? "" : "s");
#ifdef SYSLOG #ifdef SYSLOG
closelog(); closelog();
#endif #endif
@@ -160,7 +159,7 @@ va_dcl
* suitable for the mode ngIRCd is running in (daemon vs. non-daemon). * suitable for the mode ngIRCd is running in (daemon vs. non-daemon).
* If LOG_snotice is set, the log messages goes to all user with the mode +s * If LOG_snotice is set, the log messages goes to all user with the mode +s
* set and the local &SERVER channel, too. * set and the local &SERVER channel, too.
* Please note: you should use LogDebug(...) for debug messages! * Please note: you sould use LogDebug(...) for debug messages!
* @param Level syslog level (LOG_xxx) * @param Level syslog level (LOG_xxx)
* @param Format Format string like printf(). * @param Format Format string like printf().
* @param ... Further arguments. * @param ... Further arguments.

View File

@@ -19,7 +19,6 @@
#include "imp.h" #include "imp.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
@@ -38,7 +37,6 @@
#include "ngircd.h" #include "ngircd.h"
#include "pam.h" #include "pam.h"
#include "irc-info.h" #include "irc-info.h"
#include "irc-mode.h"
#include "irc-write.h" #include "irc-write.h"
#include "exp.h" #include "exp.h"
@@ -92,7 +90,7 @@ Login_User(CLIENT * Client)
#ifdef PAM #ifdef PAM
if (!Conf_PAM) { if (!Conf_PAM) {
/* Don't do any PAM authentication at all, instead emulate /* Don't do any PAM authentication at all, instead emulate
* the behavior of the daemon compiled without PAM support: * the beahiour of the daemon compiled without PAM support:
* because there can't be any "server password", all * because there can't be any "server password", all
* passwords supplied are classified as "wrong". */ * passwords supplied are classified as "wrong". */
if(Conn_Password(conn)[0] == '\0') if(Conn_Password(conn)[0] == '\0')
@@ -153,9 +151,6 @@ Login_User(CLIENT * Client)
GLOBAL bool GLOBAL bool
Login_User_PostAuth(CLIENT *Client) Login_User_PostAuth(CLIENT *Client)
{ {
REQUEST Req;
char modes[CLIENT_MODE_LEN + 1];
assert(Client != NULL); assert(Client != NULL);
if (Class_HandleServerBans(Client) != CONNECTED) if (Class_HandleServerBans(Client) != CONNECTED)
@@ -190,17 +185,8 @@ Login_User_PostAuth(CLIENT *Client)
if (!IRC_Show_MOTD(Client)) if (!IRC_Show_MOTD(Client))
return DISCONNECTED; return DISCONNECTED;
/* Set default user modes */ /* Suspend the client for a second ... */
if (Conf_DefaultUserModes[0]) { IRC_SetPenalty(Client, 1);
snprintf(modes, sizeof(modes), "+%s", Conf_DefaultUserModes);
Req.prefix = Client_ThisServer();
Req.command = "MODE";
Req.argc = 2;
Req.argv[0] = Client_ID(Client);
Req.argv[1] = modes;
IRC_MODE(Client, &Req);
} else
IRC_SetPenalty(Client, 1);
return CONNECTED; return CONNECTED;
} }
@@ -208,7 +194,7 @@ Login_User_PostAuth(CLIENT *Client)
#ifdef PAM #ifdef PAM
/** /**
* Read result of the authenticator sub-process from pipe * Read result of the authenticatior sub-process from pipe
* *
* @param r_fd File descriptor of the pipe. * @param r_fd File descriptor of the pipe.
* @param events (ignored IO specification) * @param events (ignored IO specification)
@@ -216,7 +202,6 @@ Login_User_PostAuth(CLIENT *Client)
static void static void
cb_Read_Auth_Result(int r_fd, UNUSED short events) cb_Read_Auth_Result(int r_fd, UNUSED short events)
{ {
char user[CLIENT_USER_LEN], *ptr;
CONN_ID conn; CONN_ID conn;
CLIENT *client; CLIENT *client;
int result; int result;
@@ -248,14 +233,7 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
} }
if (result == true) { if (result == true) {
/* Authentication succeeded, now set the correct user name Client_SetUser(client, Client_OrigUser(client), true);
* supplied by the client (without prepended '~' for exmaple),
* but cut it at the first '@' character: */
strlcpy(user, Client_OrigUser(client), sizeof(user));
ptr = strchr(user, '@');
if (ptr)
*ptr = '\0';
Client_SetUser(client, user, true);
(void)Login_User_PostAuth(client); (void)Login_User_PostAuth(client);
} else } else
Client_Reject(client, "Bad password", false); Client_Reject(client, "Bad password", false);

View File

@@ -55,6 +55,7 @@ static int Matche_After_Star PARAMS(( const char *p, const char *t ));
GLOBAL bool GLOBAL bool
Match( const char *Pattern, const char *String ) Match( const char *Pattern, const char *String )
{ {
/* Pattern mit String vergleichen */
if( Matche( Pattern, String ) == MATCH_VALID ) return true; if( Matche( Pattern, String ) == MATCH_VALID ) return true;
else return false; else return false;
} /* Match */ } /* Match */

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)" #define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
#define RPL_CREATED_MSG "003 %s :This server has been started %s" #define RPL_CREATED_MSG "003 %s :This server has been started %s"
#define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s" #define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s"
#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=%s CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=%s:%d :are supported on this server" #define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server" #define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d" #define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
@@ -49,7 +49,6 @@
#define RPL_NETUSERS_MSG "266 %s %lu %lu :Current global users: %lu, Max: %lu" #define RPL_NETUSERS_MSG "266 %s %lu %lu :Current global users: %lu, Max: %lu"
#define RPL_STATSCONN_MSG "250 %s :Highest connection count: %lu (%lu connections received)" #define RPL_STATSCONN_MSG "250 %s :Highest connection count: %lu (%lu connections received)"
#define RPL_WHOISSSL_MSG "275 %s %s :is connected via SSL (secure link)" #define RPL_WHOISSSL_MSG "275 %s %s :is connected via SSL (secure link)"
#define RPL_WHOISCERTFP_MSG "276 %s %s :has client certificate fingerprint %s"
#define RPL_AWAY_MSG "301 %s %s :%s" #define RPL_AWAY_MSG "301 %s %s :%s"
#define RPL_USERHOST_MSG "302 %s :" #define RPL_USERHOST_MSG "302 %s :"
@@ -57,7 +56,6 @@
#define RPL_UNAWAY_MSG "305 %s :You are no longer marked as being away" #define RPL_UNAWAY_MSG "305 %s :You are no longer marked as being away"
#define RPL_NOWAWAY_MSG "306 %s :You have been marked as being away" #define RPL_NOWAWAY_MSG "306 %s :You have been marked as being away"
#define RPL_WHOISREGNICK_MSG "307 %s %s :is a registered nick" #define RPL_WHOISREGNICK_MSG "307 %s %s :is a registered nick"
#define RPL_WHOISSERVICE_MSG "310 %s %s :is an IRC service"
#define RPL_WHOISUSER_MSG "311 %s %s %s %s * :%s" #define RPL_WHOISUSER_MSG "311 %s %s %s %s * :%s"
#define RPL_WHOISSERVER_MSG "312 %s %s %s :%s" #define RPL_WHOISSERVER_MSG "312 %s %s %s :%s"
#define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator" #define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator"

View File

@@ -264,7 +264,7 @@ main(int argc, const char *argv[])
/* Initialize the "main program": chroot environment, user and /* Initialize the "main program": chroot environment, user and
* group ID, ... */ * group ID, ... */
if (!NGIRCd_Init(NGIRCd_NoDaemon)) { if (!NGIRCd_Init(NGIRCd_NoDaemon)) {
Log(LOG_ALERT, "Fatal: Initialization failed, exiting!"); Log(LOG_ALERT, "Fatal: Initialization failed");
exit(1); exit(1);
} }
@@ -297,10 +297,10 @@ main(int argc, const char *argv[])
PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION, PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
IRCPLUSFLAGS); IRCPLUSFLAGS);
#ifdef ZLIB #ifdef ZLIB
strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID); strcat(NGIRCd_ProtoID, "Z");
#endif #endif
if (Conf_OperCanMode) if (Conf_OperCanMode)
strlcat(NGIRCd_ProtoID, "o", sizeof NGIRCd_ProtoID); strcat(NGIRCd_ProtoID, "o");
#else /* IRCPLUS */ #else /* IRCPLUS */
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s", snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION); PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
@@ -535,23 +535,21 @@ Pidfile_Create(pid_t pid)
len = snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid); len = snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
if (len < 0 || len >= (int)sizeof pidbuf) { if (len < 0 || len >= (int)sizeof pidbuf) {
Log(LOG_ERR, "Error converting process ID!"); Log(LOG_ERR, "Error converting pid");
close(pidfd); close(pidfd);
return; return;
} }
if (write(pidfd, pidbuf, (size_t)len) != (ssize_t)len) if (write(pidfd, pidbuf, (size_t)len) != (ssize_t)len)
Log(LOG_ERR, "Can't write PID file (%s): %s!", Conf_PidFile, Log( LOG_ERR, "Can't write PID file (%s): %s", Conf_PidFile, strerror( errno ));
strerror(errno));
if (close(pidfd) != 0) if( close(pidfd) != 0 )
Log(LOG_ERR, "Error closing PID file (%s): %s!", Conf_PidFile, Log( LOG_ERR, "Error closing PID file (%s): %s", Conf_PidFile, strerror( errno ));
strerror(errno));
} /* Pidfile_Create */ } /* Pidfile_Create */
/** /**
* Redirect stdin, stdout and stderr to appropriate file handles. * Redirect stdin, stdout and stderr to apropriate file handles.
* *
* @param fd The file handle stdin, stdout and stderr should be redirected to. * @param fd The file handle stdin, stdout and stderr should be redirected to.
*/ */
@@ -613,13 +611,6 @@ NGIRCd_getNobodyID(uid_t *uid, gid_t *gid )
#endif #endif
#ifdef HAVE_ARC4RANDOM
static void
Random_Init(void)
{
}
#else
static bool static bool
Random_Init_Kern(const char *file) Random_Init_Kern(const char *file)
{ {
@@ -649,7 +640,6 @@ Random_Init(void)
return; return;
srand(rand() ^ (unsigned)getpid() ^ (unsigned)time(NULL)); srand(rand() ^ (unsigned)getpid() ^ (unsigned)time(NULL));
} }
#endif
/** /**
@@ -681,22 +671,21 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
} }
/* SSL initialization */ /* SSL initialization */
if (!ConnSSL_InitLibrary()) { if (!ConnSSL_InitLibrary())
Log(LOG_ERR, "Error during SSL initialization!"); Log(LOG_WARNING,
goto out; "Error during SSL initialization, continuing without SSL ...");
}
/* Change root */ /* Change root */
if (Conf_Chroot[0]) { if (Conf_Chroot[0]) {
if (chdir(Conf_Chroot) != 0) { if (chdir(Conf_Chroot) != 0) {
Log(LOG_ERR, "Can't chdir() in ChrootDir (%s): %s!", Log(LOG_ERR, "Can't chdir() in ChrootDir (%s): %s",
Conf_Chroot, strerror(errno)); Conf_Chroot, strerror(errno));
goto out; goto out;
} }
if (chroot(Conf_Chroot) != 0) { if (chroot(Conf_Chroot) != 0) {
Log(LOG_ERR, Log(LOG_ERR,
"Can't change root directory to \"%s\": %s!", "Can't change root directory to \"%s\": %s",
Conf_Chroot, strerror(errno)); Conf_Chroot, strerror(errno));
goto out; goto out;
} else { } else {
@@ -727,16 +716,9 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
if (setgid(Conf_GID) != 0) { if (setgid(Conf_GID) != 0) {
real_errno = errno; real_errno = errno;
grp = getgrgid(Conf_GID); grp = getgrgid(Conf_GID);
Log(LOG_ERR, "Can't change group ID to %s(%u): %s!", Log(LOG_ERR, "Can't change group ID to %s(%u): %s",
grp ? grp->gr_name : "?", Conf_GID, grp ? grp->gr_name : "?", Conf_GID,
strerror(real_errno)); strerror(errno));
if (real_errno != EPERM)
goto out;
}
if (setgroups(0, NULL) != 0) {
real_errno = errno;
Log(LOG_ERR, "Can't drop supplementary group IDs: %s!",
strerror(errno));
if (real_errno != EPERM) if (real_errno != EPERM)
goto out; goto out;
} }
@@ -748,9 +730,9 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
if (setuid(Conf_UID) != 0) { if (setuid(Conf_UID) != 0) {
real_errno = errno; real_errno = errno;
pwd = getpwuid(Conf_UID); pwd = getpwuid(Conf_UID);
Log(LOG_ERR, "Can't change user ID to %s(%u): %s!", Log(LOG_ERR, "Can't change user ID to %s(%u): %s",
pwd ? pwd->pw_name : "?", Conf_UID, pwd ? pwd->pw_name : "?", Conf_UID,
strerror(real_errno)); strerror(errno));
if (real_errno != EPERM) if (real_errno != EPERM)
goto out; goto out;
} }
@@ -782,7 +764,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
setpgrp(0, getpid()); setpgrp(0, getpid());
#endif #endif
if (chdir("/") != 0) if (chdir("/") != 0)
Log(LOG_ERR, "Can't change directory to '/': %s!", Log(LOG_ERR, "Can't change directory to '/': %s",
strerror(errno)); strerror(errno));
/* Detach stdin, stdout and stderr */ /* Detach stdin, stdout and stderr */
@@ -825,8 +807,8 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
"Changed working directory to \"%s\" ...", "Changed working directory to \"%s\" ...",
pwd->pw_dir); pwd->pw_dir);
else else
Log(LOG_ERR, Log(LOG_INFO,
"Can't change working directory to \"%s\": %s!", "Notice: Can't change working directory to \"%s\": %s",
pwd->pw_dir, strerror(errno)); pwd->pw_dir, strerror(errno));
} else } else
Log(LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID); Log(LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID);

View File

@@ -47,12 +47,12 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan)
{ {
CL2CHAN *cl2chan; CL2CHAN *cl2chan;
CLIENT *cl; CLIENT *cl;
char str[COMMAND_LEN], *ptr; char str[LINE_LEN], *ptr;
bool njoin, xop; bool njoin, xop;
/* Check features of remote server */ /* Check features of remote server */
njoin = Conn_Options(Client_Conn(Client)) & CONN_RFC1459 ? false : true; njoin = Conn_Options(Client_Conn(Client)) & CONN_RFC1459 ? false : true;
xop = Client_HasFlag(Client, 'X') ? true : false; xop = strchr(Client_Flags(Client), 'X') ? true : false;
/* Get all the members of this channel */ /* Get all the members of this channel */
cl2chan = Channel_FirstMember(Chan); cl2chan = Channel_FirstMember(Chan);
@@ -68,21 +68,21 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan)
strlcat(str, ",", sizeof(str)); strlcat(str, ",", sizeof(str));
/* Prepare user prefix (ChanOp, voiced, ...) */ /* Prepare user prefix (ChanOp, voiced, ...) */
if (xop && Channel_UserHasMode(Chan, cl, 'q')) if (xop && strchr(Channel_UserModes(Chan, cl), 'q'))
strlcat(str, "~", sizeof(str)); strlcat(str, "~", sizeof(str));
if (xop && Channel_UserHasMode(Chan, cl, 'a')) if (xop && strchr(Channel_UserModes(Chan, cl), 'a'))
strlcat(str, "&", sizeof(str)); strlcat(str, "&", sizeof(str));
if (Channel_UserHasMode(Chan, cl, 'o')) if (strchr(Channel_UserModes(Chan, cl), 'o'))
strlcat(str, "@", sizeof(str)); strlcat(str, "@", sizeof(str));
if (xop && Channel_UserHasMode(Chan, cl, 'h')) if (xop && strchr(Channel_UserModes(Chan, cl), 'h'))
strlcat(str, "%", sizeof(str)); strlcat(str, "%", sizeof(str));
if (Channel_UserHasMode(Chan, cl, 'v')) if (strchr(Channel_UserModes(Chan, cl), 'v'))
strlcat(str, "+", sizeof(str)); strlcat(str, "+", sizeof(str));
strlcat(str, Client_ID(cl), sizeof(str)); strlcat(str, Client_ID(cl), sizeof(str));
/* Send the data if the buffer is "full" */ /* Send the data if the buffer is "full" */
if (strlen(str) > (sizeof(str) - CLIENT_NICK_LEN - 8)) { if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) {
if (!IRC_WriteStrClient(Client, "%s", str)) if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED; return DISCONNECTED;
snprintf(str, sizeof(str), "NJOIN %s :", snprintf(str, sizeof(str), "NJOIN %s :",
@@ -150,6 +150,72 @@ Announce_Server(CLIENT * Client, CLIENT * Server)
} /* Announce_Server */ } /* Announce_Server */
/**
* Announce existing user to a new server
* @param Client New server
* @param User Existing user in the network
*/
static bool
Announce_User(CLIENT * Client, CLIENT * User)
{
CONN_ID conn;
char *modes;
conn = Client_Conn(Client);
if (Conn_Options(conn) & CONN_RFC1459) {
/* RFC 1459 mode: separate NICK and USER commands */
if (! Conn_WriteStr(conn, "NICK %s :%d",
Client_ID(User), Client_Hops(User) + 1))
return DISCONNECTED;
if (! Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
Client_ID(User), Client_User(User),
Client_Hostname(User),
Client_ID(Client_Introducer(User)),
Client_Info(User)))
return DISCONNECTED;
modes = Client_Modes(User);
if (modes[0]) {
return Conn_WriteStr(conn, ":%s MODE %s +%s",
Client_ID(User), Client_ID(User),
modes);
}
} else {
/* RFC 2813 mode: one combined NICK or SERVICE command */
if (Client_Type(User) == CLIENT_SERVICE
&& strchr(Client_Flags(Client), 'S')) {
if (!IRC_WriteStrClient(Client,
"SERVICE %s %d * +%s %d :%s",
Client_Mask(User),
Client_MyToken(Client_Introducer(User)),
Client_Modes(User), Client_Hops(User) + 1,
Client_Info(User)))
return DISCONNECTED;
} else {
if (!IRC_WriteStrClient(Client,
"NICK %s %d %s %s %d +%s :%s",
Client_ID(User), Client_Hops(User) + 1,
Client_User(User), Client_Hostname(User),
Client_MyToken(Client_Introducer(User)),
Client_Modes(User), Client_Info(User)))
return DISCONNECTED;
}
}
if (strchr(Client_Flags(Client), 'M')) {
/* Synchronize metadata */
if (Client_HostnameCloaked(User)) {
if (!IRC_WriteStrClient(Client,
"METADATA %s cloakhost :%s",
Client_ID(User),
Client_HostnameCloaked(User)))
return DISCONNECTED;
}
}
return CONNECTED;
} /* Announce_User */
#ifdef IRCPLUS #ifdef IRCPLUS
/** /**
@@ -232,8 +298,8 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan)
if (!*modes && !*topic) if (!*modes && !*topic)
return CONNECTED; return CONNECTED;
has_k = Channel_HasMode(Chan, 'k'); has_k = strchr(modes, 'k') != NULL;
has_l = Channel_HasMode(Chan, 'l'); has_l = strchr(modes, 'l') != NULL;
/* send CHANINFO */ /* send CHANINFO */
if (!has_k && !has_l) { if (!has_k && !has_l) {
@@ -306,7 +372,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
while (c) { while (c) {
if (Client_Type(c) == CLIENT_USER || if (Client_Type(c) == CLIENT_USER ||
Client_Type(c) == CLIENT_SERVICE) { Client_Type(c) == CLIENT_SERVICE) {
if (!Client_Announce(Client, Client_ThisServer(), c)) if (!Announce_User(Client, c))
return DISCONNECTED; return DISCONNECTED;
} }
c = Client_Next(c); c = Client_Next(c);
@@ -321,7 +387,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
} }
#ifdef IRCPLUS #ifdef IRCPLUS
/* Send CHANINFO if the peer supports it */ /* Send CHANINFO if the peer supports it */
if (Client_HasFlag(Client, 'C')) { if (strchr(Client_Flags(Client), 'C')) {
if (!Send_CHANINFO(Client, chan)) if (!Send_CHANINFO(Client, chan))
return DISCONNECTED; return DISCONNECTED;
} }
@@ -335,7 +401,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
} }
#ifdef IRCPLUS #ifdef IRCPLUS
if (Client_HasFlag(Client, 'L')) { if (strchr(Client_Flags(Client), 'L')) {
LogDebug("Synchronizing INVITE- and BAN-lists ..."); LogDebug("Synchronizing INVITE- and BAN-lists ...");
if (!Synchronize_Lists(Client)) if (!Synchronize_Lists(Client))
return DISCONNECTED; return DISCONNECTED;

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -46,12 +46,12 @@ Op_NoPrivileges(CLIENT * Client, REQUEST * Req)
if (from) { if (from) {
Log(LOG_NOTICE, "No privileges: client \"%s\" (%s), command \"%s\"", Log(LOG_NOTICE, "No privileges: client \"%s\" (%s), command \"%s\"",
Req->prefix, Client_Mask(Client), Req->command); Req->prefix, Client_Mask(Client), Req->command);
return IRC_WriteErrClient(from, ERR_NOPRIVILEGES_MSG, return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from)); Client_ID(from));
} else { } else {
Log(LOG_NOTICE, "No privileges: client \"%s\", command \"%s\"", Log(LOG_NOTICE, "No privileges: client \"%s\", command \"%s\"",
Client_Mask(Client), Req->command); Client_Mask(Client), Req->command);
return IRC_WriteErrClient(Client, ERR_NOPRIVILEGES_MSG, return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client)); Client_ID(Client));
} }
} /* Op_NoPrivileges */ } /* Op_NoPrivileges */
@@ -86,7 +86,7 @@ Op_Check(CLIENT * Client, REQUEST * Req)
return c; return c;
if (!Client_HasMode(c, 'o')) if (!Client_HasMode(c, 'o'))
return NULL; return NULL;
if (Client_Conn(c) <= NONE && !Conf_AllowRemoteOper) if (!Client_OperByMe(c) && !Conf_AllowRemoteOper)
return NULL; return NULL;
/* The client is an local IRC operator, or this server is configured /* The client is an local IRC operator, or this server is configured

View File

@@ -15,7 +15,7 @@
/** /**
* @file * @file
* PAM User Authentication * PAM User Authentification
*/ */
#include "imp.h" #include "imp.h"

View File

@@ -16,7 +16,7 @@
/** /**
* @file * @file
* PAM User Authentication (header) * PAM User Authentification (header)
*/ */
GLOBAL bool PAM_Authenticate PARAMS((CLIENT *Client)); GLOBAL bool PAM_Authenticate PARAMS((CLIENT *Client));

View File

@@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -60,78 +60,74 @@ struct _NUMERIC {
static COMMAND My_Commands[] = static COMMAND My_Commands[] =
{ {
{ "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "AWAY", IRC_AWAY, CLIENT_USER, 0, 1, 0, 0, 0 }, { "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 },
{ "CAP", IRC_CAP, CLIENT_ANY, 1, 2, 0, 0, 0 }, { "CAP", IRC_CAP, 0xFFFF, 0, 0, 0 },
{ "CONNECT", IRC_CONNECT, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "CONNECT", IRC_CONNECT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
#ifdef STRICT_RFC { "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 },
{ "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0, 0, 0 }, { "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
#else { "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
{ "DIE", IRC_DIE, CLIENT_USER, 0, 1, 0, 0, 0 }, { "GLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
#endif { "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 1, 1, 0, 0, 0 }, { "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "ERROR", IRC_ERROR, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "GLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 },
{ "HELP", IRC_HELP, CLIENT_USER, 0, 1, 0, 0, 0 }, { "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 2, 2, 0, 0, 0 }, { "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "ISON", IRC_ISON, CLIENT_USER, 1, -1, 0, 0, 0 }, { "KLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 1, 2, 0, 0, 0 }, { "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 2, 3, 0, 0, 0 }, { "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 2, 2, 0, 0, 0 }, { "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "METADATA", IRC_METADATA, CLIENT_SERVER, 0, 0, 0 },
{ "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "METADATA", IRC_METADATA, CLIENT_SERVER, 3, 3, 0, 0, 0 }, { "NICK", IRC_NICK, 0xFFFF, 0, 0, 0 },
{ "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 1, -1, 0, 0, 0 }, { "NJOIN", IRC_NJOIN, CLIENT_SERVER, 0, 0, 0 },
{ "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "NOTICE", IRC_NOTICE, 0xFFFF, 0, 0, 0 },
{ "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "OPER", IRC_OPER, CLIENT_USER, 0, 0, 0 },
{ "NICK", IRC_NICK, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "NJOIN", IRC_NJOIN, CLIENT_SERVER, 2, 2, 0, 0, 0 }, { "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
{ "NOTICE", IRC_NOTICE, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "OPER", IRC_OPER, CLIENT_USER, 2, 2, 0, 0, 0 }, { "PONG", IRC_PONG, 0xFFFF, 0, 0, 0 },
{ "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 1, 2, 0, 0, 0 }, { "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "PASS", IRC_PASS, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
{ "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
{ "PONG", IRC_PONG, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 },
{ "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 },
{ "QUIT", IRC_QUIT, CLIENT_ANY, 0, 1, 0, 0, 0 }, { "SERVICE", IRC_SERVICE, 0xFFFF, 0, 0, 0 },
{ "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0, 0, 0 }, { "SERVLIST", IRC_SERVLIST, CLIENT_USER, 0, 0, 0 },
{ "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0, 0, 0 }, { "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SERVER", IRC_SERVER, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "SQUIT", IRC_SQUIT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SERVICE", IRC_SERVICE, CLIENT_ANY, 6, 6, 0, 0, 0 }, { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SERVLIST", IRC_SERVLIST, CLIENT_USER, 0, 2, 0, 0, 0 }, { "SVSNICK", IRC_SVSNICK, CLIENT_SERVER, 0, 0, 0 },
{ "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SQUIT", IRC_SQUIT, CLIENT_USER|CLIENT_SERVER, 2, 2, 0, 0, 0 }, { "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 2, 0, 0, 0 }, { "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SVSNICK", IRC_SVSNICK, CLIENT_SERVER, 2, 2, 0, 0, 0 }, { "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "USER", IRC_USER, 0xFFFF, 0, 0, 0 },
{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 },
{ "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 1, 2, 0, 0, 0 }, { "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "USER", IRC_USER, CLIENT_ANY, 0, -1, 0, 0, 0 }, { "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "USERHOST", IRC_USERHOST, CLIENT_USER, 1, -1, 0, 0, 0 }, { "WEBIRC", IRC_WEBIRC, CLIENT_UNKNOWN, 0, 0, 0 },
{ "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 },
{ "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 1, 0, 0, 0 }, { "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 1, 1, 0, 0, 0 }, { "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "WEBIRC", IRC_WEBIRC, CLIENT_UNKNOWN, 4, 4, 0, 0, 0 },
{ "WHO", IRC_WHO, CLIENT_USER, 0, 2, 0, 0, 0 },
{ "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 },
{ "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, -1, 0, 0, 0 },
#ifdef IRCPLUS #ifdef IRCPLUS
{ "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, -1, 0, 0, 0 }, { "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 },
# ifdef ICONV # ifdef ICONV
{ "CHARCONV", IRC_CHARCONV, CLIENT_USER, 1, 1, 0, 0, 0 }, { "CHARCONV", IRC_CHARCONV, CLIENT_USER, 0, 0, 0 },
# endif # endif
#endif #endif
#ifndef STRICT_RFC #ifndef STRICT_RFC
{ "GET", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, -1, 0, 0, 0 }, { "GET", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 },
{ "POST", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, -1, 0, 0, 0 }, { "POST", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 },
#endif #endif
{ NULL, NULL, 0x0, 0, 0, 0, 0, 0 } /* End-Mark */ { NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */
}; };
static void Init_Request PARAMS(( REQUEST *Req )); static void Init_Request PARAMS(( REQUEST *Req ));
@@ -161,7 +157,7 @@ Parse_GetCommandStruct( void )
* Parse a command ("request") received from a client. * Parse a command ("request") received from a client.
* *
* This function is called after the connection layer received a valid CR+LF * This function is called after the connection layer received a valid CR+LF
* terminated line of text: we assume that this is a valid IRC command and * terminated line of text: we asume that this is a valid IRC command and
* try to do something useful with it :-) * try to do something useful with it :-)
* *
* All errors are reported to the client from which the command has been * All errors are reported to the client from which the command has been
@@ -173,7 +169,7 @@ Parse_GetCommandStruct( void )
* @param Idx Index of the connection from which the command has been received. * @param Idx Index of the connection from which the command has been received.
* @param Request NULL terminated line of text (the "command"). * @param Request NULL terminated line of text (the "command").
* @return true on success (valid command or "regular" error), false if a * @return true on success (valid command or "regular" error), false if a
* fatal error occurred and the connection has been shut down. * fatal error occured and the connection has been shut down.
*/ */
GLOBAL bool GLOBAL bool
Parse_Request( CONN_ID Idx, char *Request ) Parse_Request( CONN_ID Idx, char *Request )
@@ -275,6 +271,8 @@ Parse_Request( CONN_ID Idx, char *Request )
static void static void
Init_Request( REQUEST *Req ) Init_Request( REQUEST *Req )
{ {
/* Neue Request-Struktur initialisieren */
int i; int i;
assert( Req != NULL ); assert( Req != NULL );
@@ -325,20 +323,15 @@ Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
} }
/* check if client in prefix is known */ /* check if client in prefix is known */
c = Client_Search(Req->prefix); c = Client_Search( Req->prefix );
if (!c) { if (!c) {
if (Client_Type(client) != CLIENT_SERVER) { Log(LOG_ERR,
Log(LOG_ERR, "Invalid prefix \"%s\", client not known (connection %d, command \"%s\")!?",
"Ignoring command with invalid prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!", Req->prefix, Idx, Req->command);
Req->prefix, Client_ID(client), Idx, Req->command); if (!Conn_WriteStr(Idx,
if (!Conn_WriteStr(Idx, "ERROR :Invalid prefix \"%s\", client not known",
"ERROR :Invalid prefix \"%s\"", Req->prefix))
Req->prefix)) *Closed = true;
*Closed = true;
IRC_SetPenalty(client, 2);
} else
LogDebug("Ignoring command with invalid prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
Req->prefix, Client_ID(client), Idx, Req->command);
return false; return false;
} }
@@ -347,16 +340,19 @@ Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
if (Client_NextHop(c) != client) { if (Client_NextHop(c) != client) {
if (Client_Type(c) != CLIENT_SERVER) { if (Client_Type(c) != CLIENT_SERVER) {
Log(LOG_ERR, Log(LOG_ERR,
"Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\"), closing connection!", "Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
Req->prefix, Client_ID(client), Idx, Req->command); Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
Req->command);
Conn_Close(Idx, NULL, "Spoofed prefix", true); Conn_Close(Idx, NULL, "Spoofed prefix", true);
*Closed = true; *Closed = true;
} else { } else {
Log(LOG_WARNING, Log(LOG_INFO,
"Ignoring command with spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!", "Ignoring spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\").",
Req->prefix, Client_ID(client), Idx, Req->command); Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
Req->command);
} }
return false; return false;
} }
return true; return true;
@@ -371,7 +367,7 @@ Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
*Closed = false; *Closed = false;
return true; return true;
} /* Validate_Command */ } /* Validate_Comman */
static bool static bool
@@ -423,7 +419,7 @@ Handle_Numeric(CLIENT *client, REQUEST *Req)
{ 376, IRC_Num_ENDOFMOTD } { 376, IRC_Num_ENDOFMOTD }
}; };
int i, num; int i, num;
char str[COMMAND_LEN]; char str[LINE_LEN];
CLIENT *prefix, *target = NULL; CLIENT *prefix, *target = NULL;
/* Determine target */ /* Determine target */
@@ -521,22 +517,15 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
if (!(client_type & cmd->type)) { if (!(client_type & cmd->type)) {
if (client_type == CLIENT_USER if (client_type == CLIENT_USER
&& cmd->type & CLIENT_SERVER) && cmd->type & CLIENT_SERVER)
return IRC_WriteErrClient(client, return IRC_WriteStrClient(client,
ERR_NOTREGISTEREDSERVER_MSG, ERR_NOTREGISTEREDSERVER_MSG,
Client_ID(client)); Client_ID(client));
else else
return IRC_WriteErrClient(client, return IRC_WriteStrClient(client,
ERR_NOTREGISTERED_MSG, ERR_NOTREGISTERED_MSG,
Client_ID(client)); Client_ID(client));
} }
if (Req->argc < cmd->min_argc ||
(cmd->max_argc != -1 && Req->argc > cmd->max_argc)) {
IRC_SetPenalty(client, 2);
return IRC_WriteStrClient(client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(client), Req->command);
}
/* Command is allowed for this client: call it and count /* Command is allowed for this client: call it and count
* generated bytes in output */ * generated bytes in output */
Conn_ResetWCounter(); Conn_ResetWCounter();
@@ -562,10 +551,11 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
Req->argc == 1 ? "parameter" : "parameters", Req->argc == 1 ? "parameter" : "parameters",
Req->prefix ? "" : " no" ); Req->prefix ? "" : " no" );
if (Client_Type(client) != CLIENT_SERVER) if (Client_Type(client) != CLIENT_SERVER) {
result = IRC_WriteErrClient(client, ERR_UNKNOWNCOMMAND_MSG, result = IRC_WriteStrClient(client, ERR_UNKNOWNCOMMAND_MSG,
Client_ID(client), Req->command); Client_ID(client), Req->command);
Conn_SetPenalty(Idx, 1);
}
return result; return result;
} /* Handle_Request */ } /* Handle_Request */

View File

@@ -35,8 +35,6 @@ typedef struct _COMMAND
bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request )); bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
/**< Function to handle this command */ /**< Function to handle this command */
CLIENT_TYPE type; /**< Valid client types (bit mask) */ CLIENT_TYPE type; /**< Valid client types (bit mask) */
int min_argc; /**< Min parameters */
int max_argc; /**< Max parameters */
long lcount, rcount; /**< Number of local and remote calls */ long lcount, rcount; /**< Number of local and remote calls */
long bytes; /**< Number of bytes created */ long bytes; /**< Number of bytes created */
} COMMAND; } COMMAND;

View File

@@ -50,9 +50,7 @@ GLOBAL pid_t
Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout) Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout)
{ {
pid_t pid; pid_t pid;
#ifndef HAVE_ARC4RANDOM
unsigned int seed; unsigned int seed;
#endif
assert(proc != NULL); assert(proc != NULL);
assert(pipefds != NULL); assert(pipefds != NULL);
@@ -64,9 +62,7 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout
return -1; return -1;
} }
#ifndef HAVE_ARC4RANDOM
seed = (unsigned int)rand(); seed = (unsigned int)rand();
#endif
pid = fork(); pid = fork();
switch (pid) { switch (pid) {
case -1: case -1:
@@ -77,9 +73,7 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout
return -1; return -1;
case 0: case 0:
/* New child process: */ /* New child process: */
#ifndef HAVE_ARC4RANDOM
srand(seed ^ (unsigned int)time(NULL) ^ getpid()); srand(seed ^ (unsigned int)time(NULL) ^ getpid());
#endif
Signals_Exit(); Signals_Exit();
signal(SIGTERM, Proc_GenericSignalHandler); signal(SIGTERM, Proc_GenericSignalHandler);
signal(SIGALRM, Proc_GenericSignalHandler); signal(SIGALRM, Proc_GenericSignalHandler);

View File

@@ -1,6 +1,5 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -41,6 +40,7 @@ static const int signals_catch[] = {
SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2 SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2
}; };
#ifdef DEBUG #ifdef DEBUG
static void static void
@@ -57,6 +57,7 @@ Dump_State(void)
#endif #endif
static void static void
Signal_Block(int sig) Signal_Block(int sig)
{ {
@@ -72,6 +73,7 @@ Signal_Block(int sig)
#endif #endif
} }
static void static void
Signal_Unblock(int sig) Signal_Unblock(int sig)
{ {
@@ -88,6 +90,7 @@ Signal_Unblock(int sig)
#endif #endif
} }
/** /**
* Reload the server configuration file. * Reload the server configuration file.
*/ */
@@ -114,21 +117,18 @@ Rehash(void)
* be changed during run-time */ * be changed during run-time */
if (strcmp(old_name, Conf_ServerName) != 0 ) { if (strcmp(old_name, Conf_ServerName) != 0 ) {
strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName); strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
Log(LOG_ERR, Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name.");
"Can't change \"ServerName\" on runtime! Ignored new name.");
} }
if (old_nicklen != Conf_MaxNickLength) { if (old_nicklen != Conf_MaxNickLength) {
Conf_MaxNickLength = old_nicklen; Conf_MaxNickLength = old_nicklen;
Log(LOG_ERR, Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
"Can't change \"MaxNickLength\" on runtime! Ignored new value.");
} }
/* Create new pre-defined channels */ /* Create new pre-defined channels */
Channel_InitPredefined( ); Channel_InitPredefined( );
if (!ConnSSL_InitLibrary()) if (!ConnSSL_InitLibrary())
Log(LOG_WARNING, Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys");
"Re-Initializing of SSL failed, using old keys!");
/* Start listening on sockets */ /* Start listening on sockets */
Conn_InitListeners( ); Conn_InitListeners( );
@@ -139,6 +139,7 @@ Rehash(void)
Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." ); Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
} /* Rehash */ } /* Rehash */
/** /**
* Signal handler of ngIRCd. * Signal handler of ngIRCd.
* This function is called whenever ngIRCd catches a signal sent by the * This function is called whenever ngIRCd catches a signal sent by the
@@ -197,6 +198,7 @@ Signal_Handler(int Signal)
Signal_Block(Signal); Signal_Block(Signal);
} /* Signal_Handler */ } /* Signal_Handler */
/** /**
* Signal processing handler of ngIRCd. * Signal processing handler of ngIRCd.
* This function is called from the main conn event loop in (io_dispatch) * This function is called from the main conn event loop in (io_dispatch)
@@ -229,6 +231,7 @@ Signal_Handler_BH(int Signal)
Signal_Unblock(Signal); Signal_Unblock(Signal);
} }
static void static void
Signal_Callback(int fd, short UNUSED what) Signal_Callback(int fd, short UNUSED what)
{ {
@@ -245,19 +248,19 @@ Signal_Callback(int fd, short UNUSED what)
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
return; return;
Log(LOG_EMERG, "Read from signal pipe: %s - Exiting!", Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
strerror(errno));
exit(1); exit(1);
} }
Log(LOG_EMERG, "EOF on signal pipe!? - Exiting!"); Log(LOG_EMERG, "EOF on signal pipe");
exit(1); exit(1);
} }
/** /**
* Initialize the signal handlers, catch * Initialize the signal handlers, catch
* those signals we are interested in and sets SIGPIPE to be ignored. * those signals we are interested in and sets SIGPIPE to be ignored.
* @return true if initialization was successful. * @return true if initialization was sucessful.
*/ */
bool bool
Signals_Init(void) Signals_Init(void)
@@ -303,8 +306,9 @@ Signals_Init(void)
return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback); return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
} /* Signals_Init */ } /* Signals_Init */
/** /**
* Restores signals to their default behavior. * Restores signals to their default behaviour.
* *
* This should be called after a fork() in the new * This should be called after a fork() in the new
* child prodcess, especially when we are about to call * child prodcess, especially when we are about to call

View File

@@ -15,7 +15,7 @@ EXTRA_DIST = Makefile.ng
noinst_LIBRARIES = libngportab.a noinst_LIBRARIES = libngportab.a
libngportab_a_SOURCES = strdup.c strndup.c strlcpy.c strtok_r.c vsnprintf.c waitpid.c libngportab_a_SOURCES = strdup.c strlcpy.c strtok_r.c vsnprintf.c waitpid.c
check_PROGRAMS = portabtest check_PROGRAMS = portabtest

View File

@@ -157,10 +157,6 @@ extern size_t strlcpy PARAMS(( char *dst, const char *src, size_t size ));
extern char * strdup PARAMS(( const char *s )); extern char * strdup PARAMS(( const char *s ));
#endif #endif
#ifndef HAVE_STRNDUP
extern char * strndup PARAMS((const char *s, size_t maxlen));
#endif
#ifndef HAVE_STRTOK_R #ifndef HAVE_STRTOK_R
extern char * strtok_r PARAMS((char *str, const char *delim, char **saveptr)); extern char * strtok_r PARAMS((char *str, const char *delim, char **saveptr));
#endif #endif

View File

@@ -1,37 +0,0 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
*/
#include "portab.h"
/**
* @file
* strndup() implementation. Public domain.
*/
#ifndef HAVE_STRNDUP
#include "imp.h"
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "exp.h"
GLOBAL char *
strndup(const char *s, size_t maxlen)
{
char *dup;
size_t len = strlen(s);
if (len > maxlen)
len = maxlen;
len++;
dup = malloc(len);
if (dup)
strlcpy(dup, s, len);
return dup;
}
#endif

View File

@@ -97,4 +97,3 @@ server-link-test.e
stress-A.e stress-A.e
stress-B.e stress-B.e
who-test.e who-test.e
whois-test.e

View File

@@ -1,11 +1,10 @@
#!/bin/sh #!/bin/sh
# ngIRCd Test Suite # ngIRCd Test Suite
# $Id: getpid.sh,v 1.5 2006/08/05 00:15:28 alex Exp $
# did we get a name? # did we get a name?
[ $# -ne 1 ] && exit 1 [ $# -ne 1 ] && exit 1
[ -x /bin/pidof ] && exec /bin/pidof -s $@
# detect flags for "ps" and "head" # detect flags for "ps" and "head"
UNAME=`uname` UNAME=`uname`
if [ $UNAME = "FreeBSD" ]; then if [ $UNAME = "FreeBSD" ]; then

View File

@@ -16,7 +16,6 @@
[Options] [Options]
OperCanUseMode = yes OperCanUseMode = yes
Ident = no Ident = no
IncludeDir = /var/empty
PAM = no PAM = no
[Operator] [Operator]

View File

@@ -16,7 +16,6 @@
[Options] [Options]
OperCanUseMode = yes OperCanUseMode = yes
Ident = no Ident = no
IncludeDir = /var/empty
PAM = no PAM = no
[Operator] [Operator]

View File

@@ -144,16 +144,11 @@ ngt_RandomStr(char *String, const size_t len)
assert(String != NULL); assert(String != NULL);
gettimeofday(&t, NULL); gettimeofday(&t, NULL);
#ifndef HAVE_ARC4RANDOM
srand((unsigned)(t.tv_usec * t.tv_sec)); srand((unsigned)(t.tv_usec * t.tv_sec));
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
String[i] = chars[rand() % (sizeof(chars) - 1)]; String[i] = chars[rand() % (sizeof(chars) - 1)];
} }
#else
for (i = 0; i < len; ++i)
String[i] = chars[arc4random() % (sizeof(chars) - 1)];
#endif
String[len] = '\0'; String[len] = '\0';
return String; return String;