ChangeLog | 58 +++- INSTALL | 27 +- NEWS | 24 +- contrib/Debian/changelog | 12 + contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj | 48 +++- contrib/ngircd.spec | 2 +- contrib/platformtest.sh | 52 ++-- doc/Capabilities.txt | 28 ++ doc/FAQ.txt | 14 +- doc/Makefile.am | 21 +- doc/Modes.txt | 1 + doc/Platforms.txt | 7 +- doc/Services.txt | 24 +- doc/sample-ngircd.conf.tmpl | 8 +- man/ngircd.conf.5.tmpl | 11 + src/ngircd/Makefile.am | 85 +++++- src/ngircd/client-cap.c | 73 +++++ src/ngircd/client-cap.h | 31 +++ src/ngircd/client.c | 100 ++++++- src/ngircd/client.h | 8 +- src/ngircd/conf.c | 18 +- src/ngircd/conf.h | 3 + src/ngircd/conn-ssl.c | 9 +- src/ngircd/conn.c | 40 ++- src/ngircd/defines.h | 2 +- src/ngircd/irc-cap.c | 291 ++++++++++++++++++++ src/ngircd/irc-cap.h | 24 ++ src/ngircd/irc-info.c | 96 ++++--- src/ngircd/irc-login.c | 329 ++--------------------- src/ngircd/lists.c | 6 +- src/ngircd/login.c | 243 +++++++++++++++++ src/ngircd/login.h | 25 ++ src/ngircd/messages.h | 1 + src/ngircd/ngircd.c | 13 +- src/ngircd/parse.c | 2 + src/ngircd/sighandlers.c | 5 +- 36 files changed, 1295 insertions(+), 446 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5892b16..1745ea4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,14 +9,44 @@ -- ChangeLog -- +ngIRCd Release 19.2 (2012-06-19) + + - doc/Capabilities.txt: document "multi-prefix" capability + + ngIRCd 19.2~rc1 (2012-06-13) + - New configuration option "CloakHostModeX" to configure the hostname + that gets used for IRC clients which have user mode "+x" enabled. + Up to now, the name of the IRC server itself has been used for this, + which still is the default when "CloakHostModeX" isn't set. + - Correctly handle asynchronously re-established server links: a race + condition could let the daemon loose track of an already re-established + incoming server link while preparing its own outgoing connection. + Peers that both try to connect each other could have been affected. + - Log a debug message when SIGUSR2 is handled in debug mode. + - Only allow alphanumeric characters in user-supplied user names of + USER command and IDENT replies. + - Change wording of "TLS initialized" message to make it more consistent. + - Don't leak file descriptors on error path when creating "PID files". + - Add missing mode "r" to CHANMODES in 005 "ISUPPORT" numeric. + - Update doc/Modes.txt and doc/Platforms.txt documents. + - contrib/platformtest.sh: correctly detect Open64 C compiler and handle + "CC=xxx MAKE=yyy ./platformtest.sh" calling convention. + - Add instructions for setting up Atheme IRC services. + - Implement support for IRC capability handling, the new "CAP" command, + and capablity "multi-prefix" which allows both the NAME and WHO command + handlers to return more than one "class prefix" to the client. + - Update Xcode project files: reference missing documentation files. + - Fix: Don't ignore "permission denied" errors when enabling chroot. + - FAQ: enhance description of chroot setup. + ngIRCd Release 19.1 (2012-03-19) - Fix gcc warning (v4.6.3), initialize "list" variable to NULL. - Fix typos: "recieved" -> "received", "Please not" -> "Please note", and fix lintian(1) warning ""hyphen-used-as-minus-sign", too. - - Really include _all_ patchtes to build the Anope module into the + - Really include _all_ patches to build the Anope module into the distribution archive ... ooops! - - getpid.sh: Fix testcase error for Debian using sbuild(1). + - getpid.sh: Fix test case error for Debian using sbuild(1). - Don't log "ngIRCd hello message" two times when starting up. ngIRCd Release 19 (2012-02-29) @@ -28,7 +58,7 @@ ngIRCd Release 19 (2012-02-29) - Fix building ngIRCd with old gcc versions (e. g. 2.7.2). - Correctly re-open syslog logging after reading of configuration file: Syslog logging has been initialized before reading the - configuraton, so ngIRCd always used the default facility and ignored + configuration, so ngIRCd always used the default facility and ignored the "SyslogFacility" configuration option ... Thanks to Patrik Schindler for reporting this issue! @@ -39,7 +69,7 @@ ngIRCd Release 19 (2012-02-29) - Log more information about server synchronization. - Update preliminary ngIRCd protocol module for Anope 1.9.6, which now is the only supported version. - - New numeric RPL_WHOISHOST_MSG(378), which returns the DNS hostname + - New numeric RPL_WHOISHOST_MSG(378), which returns the DNS host name (if available) and the IP address of a client in the WHOIS reply. Only the user itself and local IRC operators get this numeric. - Implement channel exception list (mode 'e'). This allows a channel @@ -85,7 +115,7 @@ ngIRCd Release 19 (2012-02-29) commands: this reduces the possibility of flooding channels with commands like "PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit. Problem noticed by Cahata, thanks! - - Display correct error message when "Server{UID|GID}" variabe in the + - Display correct error message when "Server{UID|GID}" variable in the configuration file is invalid (not a number and no existing user). - Update Copyright notices for 2012 :-) - JOIN command: don't stop handling of channel lists when a single @@ -127,8 +157,8 @@ ngIRCd Release 19 (2012-02-29) - ./configure: Fix logic and quoting of poll() detection code: only use poll() when poll.h exists as well. - Suppress 'Can't create pre-defined channel: invalid name: ""' message. - - whois-test: handle local hostname = "localhost.localdomain" using the - pattern "localhost*" for valid local hostnames. + - whois-test: handle local host name = "localhost.localdomain" using the + pattern "localhost*" for valid local host names. - sample-ngircd.conf: show correct default for "PAM" variable: The default of "PAM" is "yes" when ngIRCd has been configured to use it, so show the correct default value in the sample configuration file. @@ -242,8 +272,8 @@ ngIRCd Release 18 (2011-07-10) variable description. - Don't use "the.net" in sample-ngircd.conf, use "example.net". - Terminate incoming connections on HTTP commands "GET" and "POST". - - New configuration option "CloakHost": when set, this hostname is used for - every client instead of the real DNS hostname (or IP address). + - New configuration option "CloakHost": when set, this host name is used for + every client instead of the real DNS host name (or IP address). - New configuration option "CloakUserToNick": when enabled, ngIRCd sets every clients' user name to their nick name and hides the user name supplied by the IRC client. @@ -348,7 +378,7 @@ ngIRCd Release 17 (2010-11-07) - configure script: correctly indent IPv6 yes/no summary output. - Don't reset My_Connections[Idx].lastping when reading data, so the client lag debug-output is working again. - - Implement user mode "x": hostname cloaking (closes: #102). + - Implement user mode "x": host name cloaking (closes: #102). - Make configure switch "--docdir" work (closes: #108). - Reformat and update FAQ.txt a little bit. - INSTALL: mention SSL, IPv6, and changed handling of MotdFile. @@ -453,7 +483,7 @@ ngIRCd Release 14.1 (2009-05-05) - Allow ping timeout quit messages to show the timeout value. - Fix error handling on compressed links. - Fix server list announcement. - - Do not remove hostnames from info text. + - Do not remove host names from info text. ngIRCd Release 14 (2009-04-20) @@ -549,7 +579,7 @@ ngIRCd 0.12.0 (2008-05-13) - RPL_WHOREPLY messages generated by IRC_WHO didn't include flags (*,@,+). (Dana Dahlstrom) - IRC_WHO now supports search patterns and will test this against user - nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1. + nickname/server name/host name, etc. as required by RFC 2812, Section 3.6.1. (reported by Dana Dahlstrom) - Add test cases for "WHO" command. (Dana Dahlstrom) - Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated @@ -572,7 +602,7 @@ ngIRCd 0.11.0 (2008-01-15) ngircd to crash [from HEAD]. (CVE-2008-0285) ngIRCd 0.11.0-pre1 (2008-01-02) - - Use dotted-decimal IP address if hostname is >= 64. + - Use dotted-decimal IP address if host name is >= 64. - Add support for /STAT u (server uptime) command. - New [Server] configuration Option "Bind" allows to specify the source IP address to use when connecting to remote server. @@ -798,7 +828,7 @@ ngIRCd 0.8.0 (2004-06-26) original ircd exactly: the unnecessary but missing ":" before the last parameter has been added. - Fixed TRACE: don't output "Serv" lines for ourself; display more info. - - Results of the resolver (hostnames and IDENT names) are discarded after + - Results of the resolver (host names and IDENT names) are discarded after the client is successfully registered with the server. - Better logging while establishing and shutting down connections. - The type of service (TOS) of all sockets is set to "interactive" now. diff --git a/INSTALL b/INSTALL index 45ebe99..4e1cd2f 100644 --- a/INSTALL +++ b/INSTALL @@ -93,7 +93,8 @@ automake ("configure") should be no problem. The normal installation procedure after getting (and expanding) the source files (using a distribution archive or GIT) is as following: - 1) ./autogen.sh [only necessary when using GIT] + 0) Satisfy prerequisites + 1) ./autogen.sh [only necessary when using GIT] 2) ./configure 3) make 4) make install @@ -114,6 +115,30 @@ possible options will be installed there. You'll find its template in the doc/ directory: sample-ngircd.conf. +0): Satisfy prerequisites + +When building from source, you'll need some other software to build ngIRCd: +for example a working C compiler, make tool, GNU automake and autoconf (only +when not using a distribution archive), and a few libraries depending on the +features you want to compile in (like IDENT support, SSL, and PAM). + +If you are using one of the "big" operating systems or Linux distributions, +you can use the following commands to install all the required packages to +build the sources including all optional features and to run the test suite: + +* RedHat / Fedora based distributions: + + yum install \ + autoconf automake expect gcc glibc-devel gnutls-devel \ + libident-devel make pam-devel tcp_wrappers-devel telnet zlib-devel + +* Debian / Ubuntu based distributions: + + apt-get install \ + autoconf automake build-essential expect libgnutls-dev \ + libident-dev libpam-dev libwrap0-dev libz-dev telnet + + 1): "autogen.sh" The first step, autogen.sh, is only necessary if the configure-script isn't diff --git a/NEWS b/NEWS index 4530de1..ab0ac19 100644 --- a/NEWS +++ b/NEWS @@ -9,9 +9,21 @@ -- NEWS -- +ngIRCd Release 19.2 (2012-06-19) + + ngIRCd 19.2~rc1 (2012-06-13) + - New configuration option "CloakHostModeX" to configure the hostname + that gets used for IRC clients which have user mode "+x" enabled. + Up to now, the name of the IRC server itself has been used for this, + which still is the default when "CloakHostModeX" isn't set. + - Add instructions for setting up Atheme IRC services. + - Implement support for IRC capability handling, the new "CAP" command, + and capablity "multi-prefix" which allows both the NAME and WHO command + handlers to return more than one "class prefix" to the client. + ngIRCd Release 19.1 (2012-03-19) - - Really include _all_ patchtes to build the Anope module into the + - Really include _all_ patches to build the Anope module into the distribution archive ... ooops! ngIRCd Release 19 (2012-02-29) @@ -19,7 +31,7 @@ ngIRCd Release 19 (2012-02-29) ngIRCd 19~rc1 (2012-02-12) - Update preliminary ngIRCd protocol module for Anope 1.9.6, which now is the only supported version. - - New numeric RPL_WHOISHOST_MSG(378), which returns the DNS hostname + - New numeric RPL_WHOISHOST_MSG(378), which returns the DNS host name (if available) and the IP address of a client in the WHOIS reply. Only the user itself and local IRC operators get this numeric. - Implement channel exception list (mode 'e'). This allows a channel @@ -134,8 +146,8 @@ ngIRCd Release 18 (2011-07-10) (booleans, text strings, integer numbers) and add type information to each variable description. - Terminate incoming connections on HTTP commands "GET" and "POST". - - New configuration option "CloakHost": when set, this hostname is used for - every client instead of the real DNS hostname (or IP address). + - New configuration option "CloakHost": when set, this host name is used for + every client instead of the real DNS host name (or IP address). - New configuration option "CloakUserToNick": when enabled, ngIRCd sets every clients' user name to their nick name and hides the user name supplied by the IRC client. @@ -187,7 +199,7 @@ ngIRCd Release 17 (2010-11-07) - Enable the daemon to disable and enable "debug mode" on runtime using signal SIGUSR1, when debug code is compiled in, not only on startup using the command line parameters. - - Implement user mode "x": hostname cloaking (closes: #102). + - Implement user mode "x": host name cloaking (closes: #102). - Change MOTD file handling: ngIRCd now caches the contens of the MOTD file, so the daemon now requires a HUP signal or REHASH command to re-read the MOTD file when its content changed. @@ -292,7 +304,7 @@ ngIRCd 0.12.0 (2008-05-13) - Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and enhanced test suite to check these commands. (Dana Dahlstrom) - IRC_WHO now supports search patterns and will test this against user - nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1. + nickname/server name/host name, etc. as required by RFC 2812, Section 3.6.1. (reported by Dana Dahlstrom) - Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated as if the user had sent PART commands for all channels the user is a diff --git a/contrib/Debian/changelog b/contrib/Debian/changelog index 0df0a2e..d1438c8 100644 --- a/contrib/Debian/changelog +++ b/contrib/Debian/changelog @@ -1,3 +1,15 @@ +ngircd (19.2-0ab1) unstable; urgency=low + + * New "upstream" release: ngIRCd 19.2. + + -- Alexander Barton Tue, 19 Jun 2012 11:03:12 +0200 + +ngircd (19.2~rc1-0ab1) unstable; urgency=low + + * New "upstream" release candidate 1 for ngIRC Release 19.2. + + -- Alexander Barton Wed, 13 Jun 2012 10:59:34 +0200 + ngircd (19.1-0ab1) unstable; urgency=low * New "upstream" release: ngIRCd 19.1. diff --git a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj index 695eeee..6da1cb3 100644 --- a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj +++ b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj @@ -41,6 +41,9 @@ FAA3D27B0F139CDC00B2447E /* conn-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA3D2790F139CDC00B2447E /* conn-ssl.c */; }; FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA97C55124A271400D5BBA9 /* sighandlers.c */; }; FAACD5F514A6099C006ED74F /* class.c in Sources */ = {isa = PBXBuildFile; fileRef = FAACD5F314A6099C006ED74F /* class.c */; }; + FAD5853215271AAB00328741 /* client-cap.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853015271AAB00328741 /* client-cap.c */; }; + FAD5853515271AB800328741 /* irc-cap.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853315271AB800328741 /* irc-cap.c */; }; + FAD5853815272C2600328741 /* login.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853615272C2500328741 /* login.c */; }; FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */ = {isa = PBXBuildFile; fileRef = FAE5CC2D0CF2308A007D69B6 /* numeric.c */; }; /* End PBXBuildFile section */ @@ -231,6 +234,19 @@ FAA97C56124A271400D5BBA9 /* sighandlers.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = sighandlers.h; sourceTree = ""; }; FAACD5F314A6099C006ED74F /* class.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = class.c; sourceTree = ""; }; FAACD5F414A6099C006ED74F /* class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class.h; sourceTree = ""; }; + FAD5852F15271A7800328741 /* Capabilities.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Capabilities.txt; sourceTree = ""; }; + FAD5853015271AAB00328741 /* client-cap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "client-cap.c"; sourceTree = ""; }; + FAD5853115271AAB00328741 /* client-cap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "client-cap.h"; sourceTree = ""; }; + FAD5853315271AB800328741 /* irc-cap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "irc-cap.c"; sourceTree = ""; }; + FAD5853415271AB800328741 /* irc-cap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-cap.h"; sourceTree = ""; }; + FAD5853615272C2500328741 /* login.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = login.c; sourceTree = ""; }; + FAD5853715272C2500328741 /* login.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.h; sourceTree = ""; }; + FAE22BD215270EA300F1A5AB /* Bopm.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Bopm.txt; sourceTree = ""; }; + FAE22BD415270EA300F1A5AB /* Contributing.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Contributing.txt; sourceTree = ""; }; + FAE22BD515270EB500F1A5AB /* HowToRelease.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = HowToRelease.txt; sourceTree = ""; }; + FAE22BD615270EB500F1A5AB /* Modes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Modes.txt; sourceTree = ""; }; + FAE22BD715270EB500F1A5AB /* PAM.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PAM.txt; sourceTree = ""; }; + FAE22BD815270EC400F1A5AB /* README-Interix.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "README-Interix.txt"; sourceTree = ""; }; FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = ""; }; FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = ""; }; /* End PBXFileReference section */ @@ -298,8 +314,7 @@ FA322CD70CEF74B1001761B3 /* ngircd */ = { isa = PBXGroup; children = ( - FAA3D2790F139CDC00B2447E /* conn-ssl.c */, - FAA3D27A0F139CDC00B2447E /* conn-ssl.h */, + FA322D020CEF74B1001761B3 /* Makefile.am */, FA322CD90CEF74B1001761B3 /* array.c */, FA322CDA0CEF74B1001761B3 /* array.h */, FA322CDB0CEF74B1001761B3 /* channel.c */, @@ -308,6 +323,8 @@ FAACD5F414A6099C006ED74F /* class.h */, FA322CDD0CEF74B1001761B3 /* client.c */, FA322CDE0CEF74B1001761B3 /* client.h */, + FAD5853015271AAB00328741 /* client-cap.c */, + FAD5853115271AAB00328741 /* client-cap.h */, FA322CDF0CEF74B1001761B3 /* conf.c */, FA322CE00CEF74B1001761B3 /* conf.h */, FAA3D2780F139CDC00B2447E /* conf-ssl.h */, @@ -317,11 +334,15 @@ FA322CE40CEF74B1001761B3 /* conn-zip.h */, FA322CE50CEF74B1001761B3 /* conn.c */, FA322CE60CEF74B1001761B3 /* conn.h */, + FAA3D2790F139CDC00B2447E /* conn-ssl.c */, + FAA3D27A0F139CDC00B2447E /* conn-ssl.h */, FA322CE70CEF74B1001761B3 /* defines.h */, FA322CE80CEF74B1001761B3 /* hash.c */, FA322CE90CEF74B1001761B3 /* hash.h */, FA322CEA0CEF74B1001761B3 /* io.c */, FA322CEB0CEF74B1001761B3 /* io.h */, + FAD5853315271AB800328741 /* irc-cap.c */, + FAD5853415271AB800328741 /* irc-cap.h */, FA322CEC0CEF74B1001761B3 /* irc-channel.c */, FA322CED0CEF74B1001761B3 /* irc-channel.h */, FA322CEE0CEF74B1001761B3 /* irc-info.c */, @@ -344,7 +365,8 @@ FA322CFF0CEF74B1001761B3 /* lists.h */, FA322D000CEF74B1001761B3 /* log.c */, FA322D010CEF74B1001761B3 /* log.h */, - FA322D020CEF74B1001761B3 /* Makefile.am */, + FAD5853615272C2500328741 /* login.c */, + FAD5853715272C2500328741 /* login.h */, FA322D030CEF74B1001761B3 /* match.c */, FA322D040CEF74B1001761B3 /* match.h */, FA322D050CEF74B1001761B3 /* messages.h */, @@ -563,18 +585,25 @@ FA322D970CEF752C001761B3 /* doc */ = { isa = PBXGroup; children = ( - FAA3D2800F139D1500B2447E /* Services.txt */, - FA407F380DB15AC700271AF1 /* GIT.txt */, - FA322D9A0CEF752C001761B3 /* FAQ.txt */, FA322D9B0CEF752C001761B3 /* Makefile.am */, + FAE22BD215270EA300F1A5AB /* Bopm.txt */, + FAD5852F15271A7800328741 /* Capabilities.txt */, + FAE22BD415270EA300F1A5AB /* Contributing.txt */, + FA322D9A0CEF752C001761B3 /* FAQ.txt */, + FA407F380DB15AC700271AF1 /* GIT.txt */, + FAE22BD515270EB500F1A5AB /* HowToRelease.txt */, + FAE22BD615270EB500F1A5AB /* Modes.txt */, + FAE22BD715270EB500F1A5AB /* PAM.txt */, FA322D9C0CEF752C001761B3 /* Platforms.txt */, FA322D9D0CEF752C001761B3 /* Protocol.txt */, FA322D9E0CEF752C001761B3 /* README-AUX.txt */, FA322D9F0CEF752C001761B3 /* README-BeOS.txt */, + FAE22BD815270EC400F1A5AB /* README-Interix.txt */, FA322DA00CEF752C001761B3 /* RFC.txt */, + FAA3D2800F139D1500B2447E /* Services.txt */, + FA322DA90CEF752C001761B3 /* SSL.txt */, FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */, FA322DA20CEF752C001761B3 /* src */, - FA322DA90CEF752C001761B3 /* SSL.txt */, ); name = doc; path = ../../doc; @@ -653,7 +682,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0430; }; buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ngIRCd" */; compatibilityVersion = "Xcode 3.2"; @@ -718,6 +747,9 @@ FA2D564A11EA158B00D37A35 /* pam.c in Sources */, FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */, FAACD5F514A6099C006ED74F /* class.c in Sources */, + FAD5853215271AAB00328741 /* client-cap.c in Sources */, + FAD5853515271AB800328741 /* irc-cap.c in Sources */, + FAD5853815272C2600328741 /* login.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/contrib/ngircd.spec b/contrib/ngircd.spec index 122c56f..2041aa0 100644 --- a/contrib/ngircd.spec +++ b/contrib/ngircd.spec @@ -1,5 +1,5 @@ %define name ngircd -%define version 19.1 +%define version 19.2 %define release 1 %define prefix %{_prefix} diff --git a/contrib/platformtest.sh b/contrib/platformtest.sh index 6449a67..afe9420 100755 --- a/contrib/platformtest.sh +++ b/contrib/platformtest.sh @@ -1,7 +1,7 @@ #!/bin/sh # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2010 Alexander Barton +# Copyright (c)2001-2011 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 @@ -21,13 +21,16 @@ PLATFORM= COMPILER="unknown" VERSION="unknown" DATE=`date "+%y-%m-%d"` - -CONFIGURE= -MAKE= -CHECK= -RUN= COMMENT= +R_CONFIGURE= +R_MAKE= +R_CHECK= +R_RUN= + +[ -n "$MAKE" ] || MAKE="make" +export MAKE CC + while [ $# -gt 0 ]; do case "$1" in "-v") @@ -61,20 +64,20 @@ if [ -r ./configure ]; then echo "$NAME: Running \"./configure\" script ..." [ -n "$VERBOSE" ] && ./configure || ./configure >/dev/null if [ $? -eq 0 -a -r ./Makefile ]; then - CONFIGURE=1 - echo "$NAME: Running \"make\" ..." - [ -n "$VERBOSE" ] && make || make >/dev/null + R_CONFIGURE=1 + echo "$NAME: Running \"$MAKE\" ..." + [ -n "$VERBOSE" ] && "$MAKE" || "$MAKE" >/dev/null if [ $? -eq 0 -a -x src/ngircd/ngircd ]; then - MAKE=1 - echo "$NAME: Running \"make check\" ..." - [ -n "$VERBOSE" ] && make check || make check >/dev/null + R_MAKE=1 + echo "$NAME: Running \"$MAKE check\" ..." + [ -n "$VERBOSE" ] && "$MAKE" check || "$MAKE" check >/dev/null if [ $? -eq 0 ]; then - CHECK=1 - RUN=$CHECK + R_CHECK=1 + R_RUN=$R_CHECK else ./src/ngircd/ngircd --help 2>/dev/null \ | grep "^ngircd" >/dev/null - [ $? -eq 0 ] && RUN=1 + [ $? -eq 0 ] && R_RUN=1 fi fi fi @@ -96,9 +99,14 @@ if [ -r "Makefile" ]; then CC=$(grep "^CC = " Makefile | cut -d' ' -f3) $CC --version 2>&1 | grep -i "GCC" >/dev/null if [ $? -eq 0 ]; then - COMPILER=$($CC --version | head -1 \ - | cut -d')' -f2 | cut -d' ' -f2) - COMPILER="gcc $COMPILER" + $CC --version 2>&1 | grep -i "Open64" >/dev/null + if [ $? -eq 0 ]; then + COMPILER="Open64" + else + COMPILER=$($CC --version | head -1 \ + | cut -d')' -f2 | cut -d' ' -f2) + COMPILER="gcc $COMPILER" + fi else case "$CC" in gcc*) @@ -130,10 +138,10 @@ else [ $? -eq 0 ] && COMMENT="(3)" fi -[ -n "$CONFIGURE" ] && C="Y" || C="N" -[ -n "$MAKE" ] && M="Y" || M="N" -[ -n "$CHECK" ] && T="Y" || T="N" -[ -n "$RUN" ] && R="Y" || R="N" +[ -n "$R_CONFIGURE" ] && C="Y" || C="N" +[ -n "$R_MAKE" ] && M="Y" || M="N" +[ -n "$R_CHECK" ] && T="Y" || T="N" +[ -n "$R_RUN" ] && R="Y" || R="N" [ -n "$COMMENT" ] && COMMENT=" $COMMENT" echo diff --git a/doc/Capabilities.txt b/doc/Capabilities.txt new file mode 100644 index 0000000..d26b840 --- /dev/null +++ b/doc/Capabilities.txt @@ -0,0 +1,28 @@ + + ngIRCd - Next Generation IRC Server + http://ngircd.barton.de/ + + (c)2001-2012 Alexander Barton and Contributors. + ngIRCd is free software and published under the + terms of the GNU General Public License. + + -- Capabilities.txt -- + + +This document lists and describes the "IRC capabilities" that ngIRCd supports +and can be requested by a IRC/IRCv3 client that supports the "CAP" command. + +ngIRCd implements the "IRC Client Capabilities Extension" as described here: + + + +I. Supported Capabilities +~~~~~~~~~~~~~~~~~~~~~~~~~ + +* "multi-prefix" + + When requested, the multi-prefix client capability will cause the IRC + server to send all possible prefixes which apply to a user in NAMES and + WHO output. + + See . diff --git a/doc/FAQ.txt b/doc/FAQ.txt index b7a1c94..fe8510b 100644 --- a/doc/FAQ.txt +++ b/doc/FAQ.txt @@ -64,11 +64,19 @@ A: ngIRCd does not write its own log file. Instead, ngIRCd uses syslog(3). Q: I cannot connect to remote peers when I use the chroot option, the following is logged: "Can't resolve example.com: unknown error!". +A: see next question blow ... + +Q: When running ngIRCd inside a chroot, no IP addresses can be translated + in DNS names, errors like "Name or service not known" are logged. A: On Linux/glibc with chroot enabled you need to put some libraries inside the chroot as well, notably libnss_dns; maybe others. Unfortunately, even - linking ngIRCd statically does not help this. The only known workaround - is to either disable chroot support or to link against dietlibc instead - of glibc. (tnx to Sebastian Siewior) + linking ngIRCd statically does not help this. So you can either copy + all the required files into the chroot directory: + $ mkdir -p ./chroot/etc ./chroot/lib + $ cp -a /etc/hosts /etc/resolv.conf /etc/nsswitch.conf ./chroot/etc/ + $ cp -a /lib/libresolv* /lib/libnss_* ./chroot/lib/ + Or you can try to link ngIRCd against an other C library (like dietlibc) + that doesn't depend on NSS modules and/or these files. Q: I have added an [Oper] section, how do i log on as IRC operator? A: You can use the /OPER command in your IRC client to become an IRC operator. diff --git a/doc/Makefile.am b/doc/Makefile.am index c153fec..92e019b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,6 @@ # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2011 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 # it under the terms of the GNU General Public License as published by @@ -16,9 +16,22 @@ SUFFIXES = .tmpl -static_docs = Bopm.txt FAQ.txt GIT.txt HowToRelease.txt Modes.txt PAM.txt \ - Platforms.txt Protocol.txt README-AUX.txt README-BeOS.txt \ - README-Interix.txt RFC.txt SSL.txt Services.txt +static_docs = \ + Bopm.txt \ + Capabilities.txt \ + FAQ.txt \ + GIT.txt \ + HowToRelease.txt \ + Modes.txt \ + PAM.txt \ + Platforms.txt \ + Protocol.txt \ + README-AUX.txt \ + README-BeOS.txt \ + README-Interix.txt \ + RFC.txt \ + Services.txt \ + SSL.txt doc_templates = sample-ngircd.conf.tmpl diff --git a/doc/Modes.txt b/doc/Modes.txt index 0b0e488..e47e270 100644 --- a/doc/Modes.txt +++ b/doc/Modes.txt @@ -43,6 +43,7 @@ users to lists (e.g. "invite list", "ban list"), others have parameters mode since description b 0.5.0 Add/remove a host mask to the ban list. + e 19 Add/remove a host mask to the exception list. i 0.5.0 Channel is "invite only". I 0.5.0 Add/remove a host mask to the invite list. k 0.6.0 Channel has a "key" (a password). diff --git a/doc/Platforms.txt b/doc/Platforms.txt index 2f71038..b8e33b5 100644 --- a/doc/Platforms.txt +++ b/doc/Platforms.txt @@ -26,6 +26,8 @@ list can be updated. Thanks for your help! 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) +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) 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 hppa2.0/unknown/linux-gnu gcc 3.3.5 13~rc1 08-12-02 alex Y Y Y Y @@ -35,7 +37,7 @@ i386/apple/darwin10.8.0 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3) i386/apple/darwin11.3.0 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3) i386/pc/solaris2.9 gcc 3.2.2 CVSHEAD 04-02-24 alex Y Y Y Y i386/pc/solaris2.11 gcc 3.4.3 19 12-02-26 alex Y Y N Y (4) -i386/pc/solaris2.11 gcc 4.2.3 18 11-08-17 goetz Y Y Y Y (4) +i386/pc/solaris2.11 gcc 4.2.3 19.1 12-05-29 goetz Y Y Y Y (4) i386/unknown/freebsd5.2.1 gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y i386/unknown/freebsd6.2 gcc 3.4.6 19 12-02-26 alex Y Y Y Y (3) i386/unknown/freebsd7.3 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3) @@ -49,6 +51,7 @@ i386/unknown/openbsd3.9 gcc 3.3.5 0.10.0-p1 06-08-30 alex Y Y Y Y (3) i386/unknown/openbsd4.1 gcc 3.3.5 16 10-04-11 alex Y Y Y Y (3) i586/pc/interix3.5 gcc 3.3 19 12-02-29 alex Y Y N Y i686/pc/cygwin gcc 3.3.1 0.8.0 04-05-30 alex Y Y N Y +i686/pc/linux-gnu gcc 2.7.2 19.1 12-05-30 goetz Y Y Y Y (1) i686/pc/linux-gnu gcc 2.95.4 0.8.0 04-05-30 alex Y Y Y Y (1) i686/pc/linux-gnu gcc 3.3.5 14.1 09-08-04 alex Y Y Y Y (1) i386/pc/linux-gnu gcc 4.1.2 13~rc1 08-12-05 alex Y Y Y Y (1) @@ -62,7 +65,7 @@ m88k/dg/dgux5.4R3.10 gcc 2.5.8 CVSHEAD 04-03-15 alex Y Y ? ? mipsel/unknown/linux-gnu gcc 4.1.2 18 11-07-05 goetz Y Y N Y (1) mipsel/unknown/linux-gnu gcc 4.4.5 18 11-07-30 goetz Y Y Y Y (1) powerpc/apple/darwin6.5 gcc 3.1 0.7.x-CVS 03-04-23 alex Y Y Y Y -powerpc/apple/darwin7.9.0 gcc 3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3) +powerpc/apple/darwin7.9.0 gcc 3.3 19.1 12-05-22 goetz Y Y Y Y (3) powerpc/apple/darwin8.11.0 gcc 4.0.1 18 11-07-02 goetz Y Y Y Y (3) powerpc/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y N Y diff --git a/doc/Services.txt b/doc/Services.txt index c2059b2..944afd4 100644 --- a/doc/Services.txt +++ b/doc/Services.txt @@ -14,8 +14,9 @@ But services acting as a "regular server" are supported, either using the IRC protocol defined in RFC 1459 or RFC 2812. Support for Services has been tested using "IRC Services" version 5.x by -Andrew Church (), and a Anope 1.9 using a -preliminary protocol module for ngIRCd (). +Andrew Church (), Anope 1.9 using a +preliminary protocol module for ngIRCd (), and +Atheme 7.0.2 or later. This document describes setting up ngIRCd and these services. @@ -93,5 +94,24 @@ The documentation of IRC Services can be found here: +Setting up Atheme 7.0.2 or later +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Atheme 7.0.2 or later may be used with ngIRCd using the "ngircd" protocol +module. + +The following settings need to be in atheme.conf: + +loadmodule "modules/protocol/ngircd"; + +uplink "server.irc.net" { + password = "123abc"; + port = 6667; +}; + +The documentation of Atheme can be found in the doc/ directory of the +Atheme source distribution. + + Please let us know if you are successfully using other IRC service packages or which problems you encounter, thanks! diff --git a/doc/sample-ngircd.conf.tmpl b/doc/sample-ngircd.conf.tmpl index f696dc6..e8b2fb0 100644 --- a/doc/sample-ngircd.conf.tmpl +++ b/doc/sample-ngircd.conf.tmpl @@ -127,7 +127,13 @@ # Set this hostname for every client instead of the real one. # Please note: don't use the percentage sign ("%"), it is reserved for # future extensions! - ;CloakHost = irc.example.net + ;CloakHost = cloaked.host + + # Use this hostname for hostname cloaking on clients that have the + # user mode "+x" set, instead of the name of the server. + # Please note: don't use the percentage sign ("%"), it is reserved for + # future extensions! + ;CloakHostModeX = cloaked.user # Set every clients' user name to their nick name ;CloakUserToNick = yes diff --git a/man/ngircd.conf.5.tmpl b/man/ngircd.conf.5.tmpl index 85cf73f..0473206 100644 --- a/man/ngircd.conf.5.tmpl +++ b/man/ngircd.conf.5.tmpl @@ -220,6 +220,17 @@ don't change. Don't use the percentage sign ("%"), it is reserved for future extensions! .RE .TP +\fBCloakHostModeX\fR (string) +Use this hostname for hostname cloaking on clients that have the user mode +"+x" set, instead of the name of the server. Default: empty, use the name +of the server. +.PP +.RS +.B Please note: +.br +Don't use the percentage sign ("%"), it is reserved for future extensions! +.RE +.TP \fBCloakUserToNick\fR (boolean) Set every clients' user name to their nick name and hide the one supplied by the IRC client. Default: no. diff --git a/src/ngircd/Makefile.am b/src/ngircd/Makefile.am index 450547e..3a411a9 100644 --- a/src/ngircd/Makefile.am +++ b/src/ngircd/Makefile.am @@ -1,6 +1,6 @@ # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2010 Alexander Barton (alex@barton.de) +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) # # 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 @@ -18,21 +18,84 @@ LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \ sbin_PROGRAMS = ngircd -ngircd_SOURCES = ngircd.c array.c channel.c class.c client.c conf.c conn.c \ - conn-func.c conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c \ - irc-info.c irc-login.c irc-mode.c irc-op.c irc-oper.c irc-server.c \ - irc-write.c lists.c log.c match.c op.c numeric.c pam.c parse.c \ - proc.c resolve.c sighandlers.c +ngircd_SOURCES = \ + ngircd.c \ + array.c \ + channel.c \ + class.c \ + client.c \ + client-cap.c \ + conf.c \ + conn.c \ + conn-func.c \ + conn-ssl.c \ + conn-zip.c \ + hash.c \ + io.c \ + irc.c \ + irc-cap.c \ + irc-channel.c \ + irc-info.c \ + irc-login.c \ + irc-mode.c \ + irc-op.c \ + irc-oper.c \ + irc-server.c \ + irc-write.c \ + lists.c \ + log.c \ + login.c \ + match.c \ + numeric.c \ + op.c \ + pam.c \ + parse.c \ + proc.c \ + resolve.c \ + sighandlers.c ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr ngircd_LDADD = -lngportab -lngtool -lngipaddr -noinst_HEADERS = ngircd.h array.h channel.h class.h client.h conf.h \ - conf-ssl.h conn.h conn-func.h conn-ssl.h conn-zip.h hash.h io.h \ - irc.h irc-channel.h irc-info.h irc-login.h irc-mode.h irc-op.h \ - irc-oper.h irc-server.h irc-write.h lists.h log.h match.h numeric.h \ - op.h pam.h parse.h proc.h resolve.h sighandlers.h defines.h messages.h +noinst_HEADERS = \ + ngircd.h \ + array.h \ + channel.h \ + class.h \ + client.h \ + client-cap.h \ + conf.h \ + conf-ssl.h \ + conn.h \ + conn-func.h \ + conn-ssl.h \ + conn-zip.h \ + defines.h \ + hash.h \ + io.h \ + irc.h \ + irc-cap.h \ + irc-channel.h \ + irc-info.h \ + irc-login.h \ + irc-mode.h \ + irc-op.h \ + irc-oper.h \ + irc-server.h \ + irc-write.h \ + lists.h \ + log.h \ + login.h \ + match.h \ + messages.h \ + numeric.h \ + op.h \ + pam.h \ + parse.h \ + proc.h \ + resolve.h \ + sighandlers.h clean-local: rm -f check-version check-help lint.out diff --git a/src/ngircd/client-cap.c b/src/ngircd/client-cap.c new file mode 100644 index 0000000..b0da807 --- /dev/null +++ b/src/ngircd/client-cap.c @@ -0,0 +1,73 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 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. + */ + +#define __client_cap_c__ + +#include "portab.h" + +/** + * @file + * Functions to deal with IRC Capabilities + */ + +#include "imp.h" +#include + +#include "defines.h" +#include "conn.h" +#include "client.h" +#include "log.h" + +#include "exp.h" +#include "client-cap.h" + +GLOBAL int +Client_Cap(CLIENT *Client) +{ + assert (Client != NULL); + + return Client->capabilities; +} + +GLOBAL void +Client_CapSet(CLIENT *Client, int Cap) +{ + assert(Client != NULL); + assert(Cap >= 0); + + Client->capabilities = Cap; + LogDebug("Set new capability of \"%s\" to %d.", + Client_ID(Client), Client->capabilities); +} + +GLOBAL void +Client_CapAdd(CLIENT *Client, int Cap) +{ + assert(Client != NULL); + assert(Cap > 0); + + Client->capabilities |= Cap; + LogDebug("Add capability %d, new capability of \"%s\" is %d.", + Cap, Client_ID(Client), Client->capabilities); +} + +GLOBAL void +Client_CapDel(CLIENT *Client, int Cap) +{ + assert(Client != NULL); + assert(Cap > 0); + + Client->capabilities &= ~Cap; + LogDebug("Delete capability %d, new capability of \"%s\" is %d.", + Cap, Client_ID(Client), Client->capabilities); +} + +/* -eof- */ diff --git a/src/ngircd/client-cap.h b/src/ngircd/client-cap.h new file mode 100644 index 0000000..5532d33 --- /dev/null +++ b/src/ngircd/client-cap.h @@ -0,0 +1,31 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 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 __client_cap_h__ +#define __client_cap_h__ + +/** + * @file + * Functions to deal with IRC Capabilities (header) + */ + +#define CLIENT_CAP_PENDING 1 /* Capability negotiation pending */ +#define CLIENT_CAP_SUPPORTED 2 /* Client supports IRC capabilities */ + +#define CLIENT_CAP_MULTI_PREFIX 4 /* multi-prefix */ + +GLOBAL int Client_Cap PARAMS((CLIENT *Client)); + +GLOBAL void Client_CapSet PARAMS((CLIENT *Client, int Cap)); +GLOBAL void Client_CapAdd PARAMS((CLIENT *Client, int Cap)); +GLOBAL void Client_CapDel PARAMS((CLIENT *Client, int Cap)); + +#endif diff --git a/src/ngircd/client.c b/src/ngircd/client.c index 7e28e8f..e203cdd 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -37,6 +37,7 @@ #include "ngircd.h" #include "channel.h" #include "conf.h" +#include "conn-func.h" #include "hash.h" #include "irc-write.h" #include "log.h" @@ -69,6 +70,8 @@ static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer, static void Destroy_UserOrService PARAMS((CLIENT *Client,const char *Txt, const char *FwdMsg, bool SendQuit)); +static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix, + void *i)); GLOBAL void Client_Init( void ) @@ -822,7 +825,9 @@ Client_MaskCloaked(CLIENT *Client) return Client_Mask(Client); snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", - Client->id, Client->user, Client_ID(Client->introducer)); + Client->id, Client->user, + *Conf_CloakHostModeX ? Conf_CloakHostModeX + : Client_ID(Client->introducer)); return Mask_Buffer; } /* Client_MaskCloaked */ @@ -1142,6 +1147,46 @@ Client_Reject(CLIENT *Client, const char *Reason, bool InformClient) } +/** + * Introduce a new user or service client in the network. + * + * @param From Remote server introducing the client or NULL (local). + * @param Client New client. + * @param Type Type of the client (CLIENT_USER or CLIENT_SERVICE). + */ +GLOBAL void +Client_Introduce(CLIENT *From, CLIENT *Client, int Type) +{ + /* Set client type (user or service) */ + Client_SetType(Client, Type); + + if (From) { + if (Conf_IsService(Conf_GetServer(Client_Conn(From)), + Client_ID(Client))) + Client_SetType(Client, CLIENT_SERVICE); + LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", + Client_TypeText(Client), Client_Mask(Client), + Client_Modes(Client), Client_ID(From), + Client_ID(Client_Introducer(Client)), + Client_Hops(Client), Client_Hops(Client) > 1 ? "s": ""); + } else { + Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).", + Client_TypeText(Client), Client_Mask(Client), + Client_Conn(Client)); + Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s", + Client_ID(Client), Client_User(Client), + Client_Hostname(Client), + Conn_IPA(Client_Conn(Client)), + Client_TypeText(Client)); + } + + /* Inform other servers */ + IRC_WriteStrServersPrefixFlag_CB(From, + From != NULL ? From : Client_ThisServer(), + '\0', cb_introduceClient, (void *)Client); +} /* Client_Introduce */ + + static unsigned long Count( CLIENT_TYPE Type ) { @@ -1361,6 +1406,59 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool } /* Destroy_UserOrService */ +/** + * 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 Prefix Prefix for the generated commands. + * @param data CLIENT structure of the new client. + */ +static void +cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data) +{ + CLIENT *c = (CLIENT *)data; + CONN_ID conn; + char *modes, *user, *host; + + modes = Client_Modes(c); + user = Client_User(c) ? Client_User(c) : "-"; + host = Client_Hostname(c) ? Client_Hostname(c) : "-"; + + conn = Client_Conn(To); + if (Conn_Options(conn) & CONN_RFC1459) { + /* RFC 1459 mode: separate NICK and USER commands */ + Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c), + Client_Hops(c) + 1); + Conn_WriteStr(conn, ":%s USER %s %s %s :%s", + Client_ID(c), user, host, + Client_ID(Client_Introducer(c)), Client_Info(c)); + if (modes[0]) + Conn_WriteStr(conn, ":%s MODE %s +%s", + Client_ID(c), Client_ID(c), modes); + } else { + /* RFC 2813 mode: one combined NICK or SERVICE command */ + if (Client_Type(c) == CLIENT_SERVICE + && strchr(Client_Flags(To), 'S')) + IRC_WriteStrClientPrefix(To, Prefix, + "SERVICE %s %d * +%s %d :%s", + Client_Mask(c), + Client_MyToken(Client_Introducer(c)), + Client_Modes(c), Client_Hops(c) + 1, + Client_Info(c)); + else + IRC_WriteStrClientPrefix(To, Prefix, + "NICK %s %d %s %s %d +%s :%s", + Client_ID(c), Client_Hops(c) + 1, + user, host, + Client_MyToken(Client_Introducer(c)), + modes, Client_Info(c)); + } +} /* cb_introduceClient */ + + #ifdef DEBUG GLOBAL void diff --git a/src/ngircd/client.h b/src/ngircd/client.h index 7bb230b..4dbcc7a 100644 --- a/src/ngircd/client.h +++ b/src/ngircd/client.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) * * 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 @@ -29,12 +29,13 @@ #ifndef STRICT_RFC # define CLIENT_WAITAUTHPING 512 /* waiting for AUTH PONG from client */ #endif +#define CLIENT_WAITCAPEND 1024 /* waiting for "CAP END" command */ #define CLIENT_TYPE int #include "defines.h" -#if defined(__client_c__) | defined(S_SPLINT_S) +#if defined(__client_c__) | defined(__client_cap_c__) | defined(S_SPLINT_S) typedef struct _CLIENT { @@ -58,6 +59,7 @@ typedef struct _CLIENT 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 */ + int capabilities; /* enabled IRC capabilities */ } CLIENT; #else @@ -165,6 +167,8 @@ GLOBAL const char *Client_TypeText PARAMS((CLIENT *Client)); GLOBAL void Client_Reject PARAMS((CLIENT *Client, const char *Reason, bool InformClient)); +GLOBAL void Client_Introduce PARAMS((CLIENT *From, CLIENT *Client, int Type)); + #ifdef DEBUG GLOBAL void Client_DebugDump PARAMS((void)); diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 5426900..5f7b24f 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 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 * it under the terms of the GNU General Public License as published by @@ -358,6 +358,7 @@ Conf_Test( void ) printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper)); printf(" ChrootDir = %s\n", Conf_Chroot); printf(" CloakHost = %s\n", Conf_CloakHost); + printf(" CloakHostModeX = %s\n", Conf_CloakHostModeX); printf(" CloakUserToNick = %s\n", yesno_to_str(Conf_CloakUserToNick)); #ifdef WANT_IPV6 printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6)); @@ -492,6 +493,14 @@ Conf_SetServer( int ConfServer, CONN_ID Idx ) assert( ConfServer > NONE ); assert( Idx > NONE ); + if (Conf_Server[ConfServer].conn_id > NONE && + Conf_Server[ConfServer].conn_id != Idx) { + Log(LOG_ALERT, + "Trying to update connection index for already registered server \"%s\": %d/%d - ignored.", + Conf_Server[ConfServer].name, + Conf_Server[ConfServer].conn_id, Idx); + return; + } Conf_Server[ConfServer].conn_id = Idx; } @@ -676,6 +685,7 @@ Set_Defaults(bool InitServers) #endif strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot)); strcpy(Conf_CloakHost, ""); + strcpy(Conf_CloakHostModeX, ""); Conf_CloakUserToNick = false; Conf_ConnectIPv4 = true; #ifdef WANT_IPV6 @@ -1469,6 +1479,12 @@ Handle_OPTIONS(int Line, char *Var, char *Arg) Config_Error_TooLong(Line, Var); return; } + if (strcasecmp(Var, "CloakHostModeX") == 0) { + len = strlcpy(Conf_CloakHostModeX, Arg, sizeof(Conf_CloakHostModeX)); + if (len >= sizeof(Conf_CloakHostModeX)) + Config_Error_TooLong(Line, Var); + return; + } if (strcasecmp(Var, "CloakUserToNick") == 0) { Conf_CloakUserToNick = Check_ArgIsTrue(Arg); return; diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index be19afc..86f00fe 100644 --- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -166,6 +166,9 @@ GLOBAL bool Conf_AllowRemoteOper; /** Cloaked hostname of the clients */ GLOBAL char Conf_CloakHost[CLIENT_ID_LEN]; +/** Cloaked hostname for clients that did +x */ +GLOBAL char Conf_CloakHostModeX[CLIENT_ID_LEN]; + /** Use nick name as user name? */ GLOBAL bool Conf_CloakUserToNick; diff --git a/src/ngircd/conn-ssl.c b/src/ngircd/conn-ssl.c index ffb1b10..5d44b30 100644 --- a/src/ngircd/conn-ssl.c +++ b/src/ngircd/conn-ssl.c @@ -549,17 +549,18 @@ ConnSSL_LogCertInfo( CONNECTION *c ) assert(ssl); - Log(LOG_INFO, "New %s connection using cipher %s on socket %d.", - SSL_get_version(ssl), SSL_get_cipher(ssl), c->sock); + Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.", + c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl)); #endif #ifdef HAVE_LIBGNUTLS gnutls_session_t sess = c->ssl_state.gnutls_session; gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess); - Log(LOG_INFO, "New %s connection using cipher %s-%s on socket %d.", + Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s.", + c->sock, gnutls_protocol_get_name(gnutls_protocol_get_version(sess)), gnutls_cipher_get_name(cipher), - gnutls_mac_get_name(gnutls_mac_get(sess)), c->sock); + gnutls_mac_get_name(gnutls_mac_get(sess))); #endif } diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index b6e6280..06236fd 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 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 * it under the terms of the GNU General Public License as published by @@ -1935,6 +1935,14 @@ New_Server( int Server , ng_ipaddr_t *dest) assert( Server > NONE ); + /* Make sure that the remote server hasn't re-linked to this server + * asynchronously on its own */ + if (Conf_Server[Server].conn_id > NONE) { + Log(LOG_INFO, + "Connection to \"%s\" meanwhile re-established, aborting preparation."); + return; + } + if (!ng_ipaddr_tostr_r(dest, ip_str)) { Log(LOG_WARNING, "New_Server: Could not convert IP to string"); return; @@ -2008,7 +2016,7 @@ New_Server( int Server , ng_ipaddr_t *dest) Client_SetToken( c, TOKEN_OUTBOUND ); /* Register connection */ - Conf_Server[Server].conn_id = new_sock; + Conf_SetServer(Server, new_sock); My_Connections[new_sock].sock = new_sock; My_Connections[new_sock].addr = *dest; My_Connections[new_sock].client = c; @@ -2174,6 +2182,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) char *identptr; #ifdef IDENTAUTH char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN]; + char *ptr; #else char readbuf[HOST_LEN + 1]; #endif @@ -2226,11 +2235,30 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) #ifdef IDENTAUTH ++identptr; if (*identptr) { - Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr); - Client_SetUser(c, identptr, true); - if (Conf_NoticeAuth) + ptr = identptr; + while (*ptr) { + if ((*ptr < '0' || *ptr > '9') && + (*ptr < 'A' || *ptr > 'Z') && + (*ptr < 'a' || *ptr > 'z')) + break; + ptr++; + } + if (*ptr) { + /* Erroneous IDENT reply */ + Log(LOG_NOTICE, + "Got invalid IDENT reply for connection %d! Ignored.", + i); + } else { + Log(LOG_INFO, + "IDENT lookup for connection %d: \"%s\".", + i, identptr); + Client_SetUser(c, identptr, true); + } + if (Conf_NoticeAuth) { (void)Conn_WriteStr(i, - "NOTICE AUTH :*** Got ident response"); + "NOTICE AUTH :*** Got %sident response", + *ptr ? "invalid " : ""); + } } else { Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i); if (Conf_NoticeAuth && Conf_Ident) diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index c63abc9..953eac3 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -161,7 +161,7 @@ #define USERMODES "acCiorRswx" /** Supported channel modes. */ -#define CHANMODES "beiIklmnoOPRstvz" +#define CHANMODES "beiIklmnoOPrRstvz" /** Away message for users connected to linked servers. */ #define DEFAULT_AWAY_MSG "Away" diff --git a/src/ngircd/irc-cap.c b/src/ngircd/irc-cap.c new file mode 100644 index 0000000..2ea4c9a --- /dev/null +++ b/src/ngircd/irc-cap.c @@ -0,0 +1,291 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 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. + */ + +#include "portab.h" + +/** + * @file + * Handler for IRC capability ("CAP") commands + */ + +#include "imp.h" +#include +#include + +#include "defines.h" +#include "conn.h" +#include "channel.h" +#include "client-cap.h" +#include "irc-write.h" +#include "log.h" +#include "login.h" +#include "messages.h" +#include "parse.h" + +#include "exp.h" +#include "irc-cap.h" + +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". + * + * @param Client The client to handle. + */ +void +Set_CAP_Negotiation(CLIENT *Client) +{ + assert(Client != NULL); + + if (Client_Type(Client) != CLIENT_USER) + Client_CapAdd(Client, CLIENT_CAP_PENDING); + Client_CapAdd(Client, CLIENT_CAP_SUPPORTED); +} + +/** + * Parse capability string and return numeric flag value. + * + * @param Args The string containing space-separated capability names. + * @return Changed capability flags or 0 on error. + */ +int +Parse_CAP(int Capabilities, char *Args) +{ + static char tmp[COMMAND_LEN]; + char *ptr; + + assert(Args != NULL); + + strlcpy(tmp, Args, sizeof(tmp)); + + ptr = strtok(tmp, " "); + while (ptr) { + if (*ptr == '-') { + /* drop capabilities */ + ptr++; + if (strcmp(ptr, "multi-prefix") == 0) + Capabilities &= ~CLIENT_CAP_MULTI_PREFIX; + else + return -1; + } else { + /* request capabilities */ + if (strcmp(ptr, "multi-prefix") == 0) + Capabilities |= CLIENT_CAP_MULTI_PREFIX; + else + return -1; + } + ptr = strtok(NULL, " "); + } + + return Capabilities; +} + +/** + * Return textual representation of capability flags. + * + * Please note: this function returns a pointer to a global buffer and + * therefore isn't thread safe! + * + * @param Capabilities Capability flags (bitmask). + * @return Pointer to textual representation. + */ +char +*Get_CAP_String(int Capabilities) +{ + static char txt[COMMAND_LEN]; + + txt[0] = '\0'; + + if (Capabilities & CLIENT_CAP_MULTI_PREFIX) + strlcat(txt, "multi-prefix ", sizeof(txt)); + + return txt; +} + +/* -eof- */ diff --git a/src/ngircd/irc-cap.h b/src/ngircd/irc-cap.h new file mode 100644 index 0000000..7cd4c84 --- /dev/null +++ b/src/ngircd/irc-cap.h @@ -0,0 +1,24 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de). + * + * 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_cap_h__ +#define __irc_cap_h__ + +/** + * @file + * Handler for IRC capability ("CAP") commands (header) + */ + +GLOBAL bool IRC_CAP PARAMS((CLIENT *Client, REQUEST *Req)); + +#endif + +/* -eof- */ diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index 841e6e6..0ea8587 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -39,6 +39,7 @@ #include "parse.h" #include "irc.h" #include "irc-write.h" +#include "client-cap.h" #include "exp.h" #include "irc-info.h" @@ -807,8 +808,16 @@ who_flags_status(const char *client_modes) static const char * -who_flags_qualifier(const char *chan_user_modes) +who_flags_qualifier(CLIENT *Client, const char *chan_user_modes) { + assert(Client != NULL); + + if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) { + if (strchr(chan_user_modes, 'o') && + strchr(chan_user_modes, 'v')) + return "@+"; + } + if (strchr(chan_user_modes, 'o')) return "@"; else if (strchr(chan_user_modes, 'v')) @@ -865,7 +874,7 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) strlcat(flags, "*", sizeof(flags)); chan_user_modes = Channel_UserModes(Chan, c); - strlcat(flags, who_flags_qualifier(chan_user_modes), + strlcat(flags, who_flags_qualifier(c, chan_user_modes), sizeof(flags)); if (!write_whoreply(Client, c, Channel_Name(Chan), @@ -1078,7 +1087,7 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) if (str[strlen(str) - 1] != ':') strlcat(str, " ", sizeof(str)); - strlcat(str, who_flags_qualifier(Channel_UserModes(chan, c)), + strlcat(str, who_flags_qualifier(c, Channel_UserModes(chan, c)), sizeof(str)); strlcat(str, Channel_Name(chan), sizeof(str)); @@ -1524,60 +1533,77 @@ IRC_Show_MOTD( CLIENT *Client ) } /* IRC_Show_MOTD */ +/** + * Send NAMES reply for a specific client and channel. + * + * @param Client The client requesting the NAMES information. + * @param Chan The channel + * @return CONNECTED or DISCONNECTED. + */ GLOBAL bool -IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan ) +IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) { bool is_visible, is_member; char str[LINE_LEN + 1]; CL2CHAN *cl2chan; CLIENT *cl; - assert( Client != NULL ); - assert( Chan != NULL ); + assert(Client != NULL); + assert(Chan != NULL); - if( Channel_IsMemberOf( Chan, Client )) is_member = true; - else is_member = false; + if (Channel_IsMemberOf(Chan, Client)) + is_member = true; + else + is_member = false; /* Do not print info on channel memberships to anyone that is not member? */ if (Conf_MorePrivacy && !is_member) return CONNECTED; /* Secret channel? */ - if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED; + if (!is_member && strchr(Channel_Modes(Chan), 's')) + return CONNECTED; - /* Alle Mitglieder suchen */ - snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); - cl2chan = Channel_FirstMember( Chan ); - while( cl2chan ) - { - cl = Channel_GetClient( cl2chan ); + snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), "=", + Channel_Name(Chan)); + cl2chan = Channel_FirstMember(Chan); + while (cl2chan) { + cl = Channel_GetClient(cl2chan); - if( strchr( Client_Modes( cl ), 'i' )) is_visible = false; - else is_visible = true; + if (strchr(Client_Modes(cl), 'i')) + is_visible = false; + else + is_visible = true; - if( is_member || is_visible ) - { - /* Nick anhaengen */ - if( str[strlen( str ) - 1] != ':' ) strlcat( str, " ", sizeof( str )); - if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strlcat( str, "@", sizeof( str )); - else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strlcat( str, "+", sizeof( str )); - strlcat( str, Client_ID( cl ), sizeof( str )); + if (is_member || is_visible) { + if (str[strlen(str) - 1] != ':') + strlcat(str, " ", sizeof(str)); + if (Client_Cap(cl) & CLIENT_CAP_MULTI_PREFIX) { + if (strchr(Channel_UserModes(Chan, cl), 'o') && + strchr(Channel_UserModes(Chan, cl), 'v')) + strlcat(str, "@+", sizeof(str)); + } else { + if (strchr(Channel_UserModes(Chan, cl), 'o')) + strlcat(str, "@", sizeof(str)); + else if (strchr(Channel_UserModes(Chan, cl), 'v')) + strlcat(str, "+", sizeof(str)); + } + strlcat(str, Client_ID(cl), sizeof(str)); - if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 )) - { - /* Zeile wird zu lang: senden! */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); + if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 4)) { + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, + Client_ID(Client), "=", + Channel_Name(Chan)); } } - /* naechstes Mitglied suchen */ - cl2chan = Channel_NextMember( Chan, cl2chan ); + cl2chan = Channel_NextMember(Chan, cl2chan); } - if( str[strlen( str ) - 1] != ':') - { - /* Es sind noch Daten da, die gesendet werden muessen */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; + if (str[strlen(str) - 1] != ':') { + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; } return CONNECTED; diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index 133a0e5..3fb1b90 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -18,22 +18,17 @@ #include "imp.h" #include -#include #include #include #include -#include -#include -#include "ngircd.h" #include "conn-func.h" #include "class.h" #include "conf.h" #include "channel.h" -#include "io.h" #include "log.h" +#include "login.h" #include "messages.h" -#include "pam.h" #include "parse.h" #include "irc.h" #include "irc-info.h" @@ -42,18 +37,7 @@ #include "exp.h" #include "irc-login.h" - -static bool Hello_User PARAMS(( CLIENT *Client )); -static bool Hello_User_PostAuth PARAMS(( CLIENT *Client )); static void Kill_Nick PARAMS(( char *Nick, char *Reason )); -static void Introduce_Client PARAMS((CLIENT *To, CLIENT *Client, int Type)); - -static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix, - void *i)); - -#ifdef PAM -static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events)); -#endif /** * Handler for the IRC "PASS" command. @@ -285,7 +269,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) /* If we received a valid USER command already then * register the new client! */ if( Client_Type( Client ) == CLIENT_GOTUSER ) - return Hello_User( Client ); + return Login_User( Client ); else Client_SetType( Client, CLIENT_GOTNICK ); } else { @@ -395,7 +379,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) Client_Mask(c)); Client_SetType(c, CLIENT_GOTNICK); } else - Introduce_Client(Client, c, CLIENT_USER); + Client_Introduce(Client, c, CLIENT_USER); return CONNECTED; } @@ -416,9 +400,7 @@ GLOBAL bool IRC_USER(CLIENT * Client, REQUEST * Req) { CLIENT *c; -#ifdef IDENTAUTH char *ptr; -#endif assert(Client != NULL); assert(Req != NULL); @@ -436,7 +418,19 @@ IRC_USER(CLIENT * Client, REQUEST * Req) Client_ID(Client), Req->command); - /* User name */ + /* User name: only alphanumeric characters are allowed! */ + ptr = Req->argv[0]; + while (*ptr) { + if ((*ptr < '0' || *ptr > '9') && + (*ptr < 'A' || *ptr > 'Z') && + (*ptr < 'a' || *ptr > 'z')) { + Conn_Close(Client_Conn(Client), NULL, + "Invalid user name", true); + return DISCONNECTED; + } + ptr++; + } + #ifdef IDENTAUTH ptr = Client_User(Client); if (!ptr || !*ptr || *ptr == '~') @@ -457,7 +451,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req) LogDebug("Connection %d: got valid USER command ...", Client_Conn(Client)); if (Client_Type(Client) == CLIENT_GOTNICK) - return Hello_User(Client); + return Login_User(Client); else Client_SetType(Client, CLIENT_GOTUSER); return CONNECTED; @@ -487,7 +481,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req) /* RFC 1459 style user registration? * Introduce client to network: */ if (Client_Type(c) == CLIENT_GOTNICK) - Introduce_Client(Client, c, CLIENT_USER); + Client_Introduce(Client, c, CLIENT_USER); return CONNECTED; } else if (Client_Type(Client) == CLIENT_USER) { @@ -601,7 +595,7 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req) return CONNECTED; } - Introduce_Client(Client, c, CLIENT_SERVICE); + Client_Introduce(Client, c, CLIENT_SERVICE); return CONNECTED; } /* IRC_SERVICE */ @@ -880,7 +874,7 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) if (auth_ping == atoi(Req->argv[0])) { Conn_SetAuthPing(conn, 0); if (Client_Type(Client) == CLIENT_WAITAUTHPING) - Hello_User(Client); + Login_User(Client); } else if (!IRC_WriteStrClient(Client, "To connect, type /QUOTE PONG %ld", @@ -904,196 +898,6 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) /** - * Initiate client registration. - * - * This function is called after the daemon received the required NICK and - * USER commands of a new client. If the daemon is compiled with support for - * PAM, the authentication sub-processs is forked; otherwise the global server - * password is checked. - * - * @param Client The client logging in. - * @returns CONNECTED or DISCONNECTED. - */ -static bool -Hello_User(CLIENT * Client) -{ -#ifdef PAM - int pipefd[2], result; - pid_t pid; -#endif - CONN_ID conn; - - assert(Client != NULL); - conn = Client_Conn(Client); - -#ifndef STRICT_RFC - if (Conf_AuthPing) { - /* Did we receive the "auth PONG" already? */ - if (Conn_GetAuthPing(conn)) { - Client_SetType(Client, CLIENT_WAITAUTHPING); - LogDebug("Connection %d: Waiting for AUTH PONG ...", conn); - return CONNECTED; - } - } -#endif - -#ifdef PAM - if (!Conf_PAM) { - /* Don't do any PAM authentication at all, instead emulate - * the beahiour of the daemon compiled without PAM support: - * because there can't be any "server password", all - * passwords supplied are classified as "wrong". */ - if(Client_Password(Client)[0] == '\0') - return Hello_User_PostAuth(Client); - Client_Reject(Client, "Non-empty password", false); - return DISCONNECTED; - } - - if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) { - /* Clients are not required to send a password and to be PAM- - * authenticated at all. If not, they won't become "identified" - * and keep the "~" in their supplied user name. - * Therefore it is sensible to either set Conf_PAMisOptional or - * to enable IDENT lookups -- not both. */ - return Hello_User_PostAuth(Client); - } - - /* Fork child process for PAM authentication; and make sure that the - * process timeout is set higher than the login timeout! */ - pid = Proc_Fork(Conn_GetProcStat(conn), pipefd, - cb_Read_Auth_Result, Conf_PongTimeout + 1); - if (pid > 0) { - LogDebug("Authenticator for connection %d created (PID %d).", - conn, pid); - return CONNECTED; - } else { - /* Sub process */ - Log_Init_Subprocess("Auth"); - Conn_CloseAllSockets(NONE); - result = PAM_Authenticate(Client); - if (write(pipefd[1], &result, sizeof(result)) != sizeof(result)) - Log_Subprocess(LOG_ERR, - "Failed to pipe result to parent!"); - Log_Exit_Subprocess("Auth"); - exit(0); - } -#else - /* Check global server password ... */ - if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) { - /* Bad password! */ - Client_Reject(Client, "Bad server password", false); - return DISCONNECTED; - } - return Hello_User_PostAuth(Client); -#endif -} - - -#ifdef PAM - -/** - * Read result of the authenticatior sub-process from pipe - * - * @param r_fd File descriptor of the pipe. - * @param events (ignored IO specification) - */ -static void -cb_Read_Auth_Result(int r_fd, UNUSED short events) -{ - CONN_ID conn; - CLIENT *client; - int result; - size_t len; - PROC_STAT *proc; - - LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events); - conn = Conn_GetFromProc(r_fd); - if (conn == NONE) { - /* Ops, none found? Probably the connection has already - * been closed!? We'll ignore that ... */ - io_close(r_fd); - LogDebug("Auth: Got callback for unknown connection!?"); - return; - } - proc = Conn_GetProcStat(conn); - client = Conn_GetClient(conn); - - /* Read result from pipe */ - len = Proc_Read(proc, &result, sizeof(result)); - Proc_Close(proc); - if (len == 0) - return; - - if (len != sizeof(result)) { - Log(LOG_CRIT, "Auth: Got malformed result!"); - Client_Reject(client, "Internal error", false); - return; - } - - if (result == true) { - Client_SetUser(client, Client_OrigUser(client), true); - (void)Hello_User_PostAuth(client); - } else - Client_Reject(client, "Bad password", false); -} - -#endif - - -/** - * Finish client registration. - * - * Introduce the new client to the network and send all "hello messages" - * to it after authentication has been succeeded. - * - * @param Client The client logging in. - * @returns CONNECTED or DISCONNECTED. - */ -static bool -Hello_User_PostAuth(CLIENT *Client) -{ - assert(Client != NULL); - - if (Class_HandleServerBans(Client) != CONNECTED) - return DISCONNECTED; - - Introduce_Client(NULL, Client, CLIENT_USER); - - if (!IRC_WriteStrClient - (Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client))) - return false; - if (!IRC_WriteStrClient - (Client, RPL_YOURHOST_MSG, Client_ID(Client), - Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU, - TARGET_VENDOR, TARGET_OS)) - return false; - if (!IRC_WriteStrClient - (Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr)) - return false; - if (!IRC_WriteStrClient - (Client, RPL_MYINFO_MSG, Client_ID(Client), - Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES, - CHANMODES)) - return false; - - /* Features supported by this server (005 numeric, ISUPPORT), - * see for details. */ - if (!IRC_Send_ISUPPORT(Client)) - return DISCONNECTED; - - if (!IRC_Send_LUSERS(Client)) - return DISCONNECTED; - if (!IRC_Show_MOTD(Client)) - return DISCONNECTED; - - /* Suspend the client for a second ... */ - IRC_SetPenalty(Client, 1); - - return CONNECTED; -} - - -/** * Kill all users with a specific nick name in the network. * * @param Nick Nick name. @@ -1119,97 +923,4 @@ Kill_Nick(char *Nick, char *Reason) } /* Kill_Nick */ -/** - * Introduce a new user or service client in the network. - * - * @param From Remote server introducing the client or NULL (local). - * @param Client New client. - * @param Type Type of the client (CLIENT_USER or CLIENT_SERVICE). - */ -static void -Introduce_Client(CLIENT *From, CLIENT *Client, int Type) -{ - /* Set client type (user or service) */ - Client_SetType(Client, Type); - - if (From) { - if (Conf_IsService(Conf_GetServer(Client_Conn(From)), - Client_ID(Client))) - Client_SetType(Client, CLIENT_SERVICE); - LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", - Client_TypeText(Client), Client_Mask(Client), - Client_Modes(Client), Client_ID(From), - Client_ID(Client_Introducer(Client)), - Client_Hops(Client), Client_Hops(Client) > 1 ? "s": ""); - } else { - Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).", - Client_TypeText(Client), Client_Mask(Client), - Client_Conn(Client)); - Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s", - Client_ID(Client), Client_User(Client), - Client_Hostname(Client), - Conn_IPA(Client_Conn(Client)), - Client_TypeText(Client)); - } - - /* Inform other servers */ - IRC_WriteStrServersPrefixFlag_CB(From, - From != NULL ? From : Client_ThisServer(), - '\0', cb_introduceClient, (void *)Client); -} /* Introduce_Client */ - - -/** - * 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 Prefix Prefix for the generated commands. - * @param data CLIENT structure of the new client. - */ -static void -cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data) -{ - CLIENT *c = (CLIENT *)data; - CONN_ID conn; - char *modes, *user, *host; - - modes = Client_Modes(c); - user = Client_User(c) ? Client_User(c) : "-"; - host = Client_Hostname(c) ? Client_Hostname(c) : "-"; - - conn = Client_Conn(To); - if (Conn_Options(conn) & CONN_RFC1459) { - /* RFC 1459 mode: separate NICK and USER commands */ - Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c), - Client_Hops(c) + 1); - Conn_WriteStr(conn, ":%s USER %s %s %s :%s", - Client_ID(c), user, host, - Client_ID(Client_Introducer(c)), Client_Info(c)); - if (modes[0]) - Conn_WriteStr(conn, ":%s MODE %s +%s", - Client_ID(c), Client_ID(c), modes); - } else { - /* RFC 2813 mode: one combined NICK or SERVICE command */ - if (Client_Type(c) == CLIENT_SERVICE - && strchr(Client_Flags(To), 'S')) - IRC_WriteStrClientPrefix(To, Prefix, - "SERVICE %s %d * +%s %d :%s", - Client_Mask(c), - Client_MyToken(Client_Introducer(c)), - Client_Modes(c), Client_Hops(c) + 1, - Client_Info(c)); - else - IRC_WriteStrClientPrefix(To, Prefix, - "NICK %s %d %s %s %d +%s :%s", - Client_ID(c), Client_Hops(c) + 1, - user, host, - Client_MyToken(Client_Introducer(c)), - modes, Client_Info(c)); - } -} /* cb_introduceClient */ - - /* -eof- */ diff --git a/src/ngircd/lists.c b/src/ngircd/lists.c index 4f57ca7..5c6c52c 100644 --- a/src/ngircd/lists.c +++ b/src/ngircd/lists.c @@ -147,10 +147,8 @@ Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil, strlcpy(newelem->mask, Mask, sizeof(newelem->mask)); if (Reason) { - newelem->reason = malloc(strlen(Reason) + 1); - if (newelem->reason) - strlcpy(newelem->reason, Reason, strlen(Reason) + 1); - else + newelem->reason = strdup(Reason); + if (!newelem->reason) Log(LOG_EMERG, "Can't allocate memory for new list reason text!"); } diff --git a/src/ngircd/login.c b/src/ngircd/login.c new file mode 100644 index 0000000..7f0299c --- /dev/null +++ b/src/ngircd/login.c @@ -0,0 +1,243 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 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. + */ + +#include "portab.h" + +/** + * @file + * Functions to deal with client logins + */ + +#include "imp.h" +#include +#include +#include +#include +#include + +#include "defines.h" +#include "conn.h" +#include "class.h" +#include "client.h" +#include "client-cap.h" +#include "channel.h" +#include "conf.h" +#include "io.h" +#include "parse.h" +#include "log.h" +#include "messages.h" +#include "ngircd.h" +#include "pam.h" +#include "irc-info.h" +#include "irc-write.h" + +#include "exp.h" +#include "login.h" + +#ifdef PAM +static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events)); +#endif + +/** + * Initiate client login. + * + * This function is called after the daemon received the required NICK and + * USER commands of a new client. If the daemon is compiled with support for + * PAM, the authentication sub-processs is forked; otherwise the global server + * password is checked. + * + * @param Client The client logging in. + * @returns CONNECTED or DISCONNECTED. + */ +GLOBAL bool +Login_User(CLIENT * Client) +{ +#ifdef PAM + int pipefd[2], result; + pid_t pid; +#endif + CONN_ID conn; + + assert(Client != NULL); + conn = Client_Conn(Client); + +#ifndef STRICT_RFC + if (Conf_AuthPing) { + /* Did we receive the "auth PONG" already? */ + if (Conn_GetAuthPing(conn)) { + Client_SetType(Client, CLIENT_WAITAUTHPING); + LogDebug("Connection %d: Waiting for AUTH PONG ...", conn); + return CONNECTED; + } + } +#endif + + /* Still waiting for "CAP END" command? */ + if (Client_Cap(Client) & CLIENT_CAP_PENDING) { + Client_SetType(Client, CLIENT_WAITCAPEND); + LogDebug("Connection %d: Waiting for CAP END ...", conn); + return CONNECTED; + } + +#ifdef PAM + if (!Conf_PAM) { + /* Don't do any PAM authentication at all, instead emulate + * the beahiour of the daemon compiled without PAM support: + * because there can't be any "server password", all + * passwords supplied are classified as "wrong". */ + if(Client_Password(Client)[0] == '\0') + return Login_User_PostAuth(Client); + Client_Reject(Client, "Non-empty password", false); + return DISCONNECTED; + } + + if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) { + /* Clients are not required to send a password and to be PAM- + * authenticated at all. If not, they won't become "identified" + * and keep the "~" in their supplied user name. + * Therefore it is sensible to either set Conf_PAMisOptional or + * to enable IDENT lookups -- not both. */ + return Login_User_PostAuth(Client); + } + + /* Fork child process for PAM authentication; and make sure that the + * process timeout is set higher than the login timeout! */ + pid = Proc_Fork(Conn_GetProcStat(conn), pipefd, + cb_Read_Auth_Result, Conf_PongTimeout + 1); + if (pid > 0) { + LogDebug("Authenticator for connection %d created (PID %d).", + conn, pid); + return CONNECTED; + } else { + /* Sub process */ + Log_Init_Subprocess("Auth"); + Conn_CloseAllSockets(NONE); + result = PAM_Authenticate(Client); + if (write(pipefd[1], &result, sizeof(result)) != sizeof(result)) + Log_Subprocess(LOG_ERR, + "Failed to pipe result to parent!"); + Log_Exit_Subprocess("Auth"); + exit(0); + } +#else + /* Check global server password ... */ + if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) { + /* Bad password! */ + Client_Reject(Client, "Bad server password", false); + return DISCONNECTED; + } + return Login_User_PostAuth(Client); +#endif +} + +/** + * Finish client registration. + * + * Introduce the new client to the network and send all "hello messages" + * to it after authentication has been succeeded. + * + * @param Client The client logging in. + * @return CONNECTED or DISCONNECTED. + */ +GLOBAL bool +Login_User_PostAuth(CLIENT *Client) +{ + assert(Client != NULL); + + if (Class_HandleServerBans(Client) != CONNECTED) + return DISCONNECTED; + + Client_Introduce(NULL, Client, CLIENT_USER); + + if (!IRC_WriteStrClient + (Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client))) + return false; + if (!IRC_WriteStrClient + (Client, RPL_YOURHOST_MSG, Client_ID(Client), + Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU, + TARGET_VENDOR, TARGET_OS)) + return false; + if (!IRC_WriteStrClient + (Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr)) + return false; + if (!IRC_WriteStrClient + (Client, RPL_MYINFO_MSG, Client_ID(Client), + Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES, + CHANMODES)) + return false; + + /* Features supported by this server (005 numeric, ISUPPORT), + * see for details. */ + if (!IRC_Send_ISUPPORT(Client)) + return DISCONNECTED; + + if (!IRC_Send_LUSERS(Client)) + return DISCONNECTED; + if (!IRC_Show_MOTD(Client)) + return DISCONNECTED; + + /* Suspend the client for a second ... */ + IRC_SetPenalty(Client, 1); + + return CONNECTED; +} + +#ifdef PAM + +/** + * Read result of the authenticatior sub-process from pipe + * + * @param r_fd File descriptor of the pipe. + * @param events (ignored IO specification) + */ +static void +cb_Read_Auth_Result(int r_fd, UNUSED short events) +{ + CONN_ID conn; + CLIENT *client; + int result; + size_t len; + PROC_STAT *proc; + + LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events); + conn = Conn_GetFromProc(r_fd); + if (conn == NONE) { + /* Ops, none found? Probably the connection has already + * been closed!? We'll ignore that ... */ + io_close(r_fd); + LogDebug("Auth: Got callback for unknown connection!?"); + return; + } + proc = Conn_GetProcStat(conn); + client = Conn_GetClient(conn); + + /* Read result from pipe */ + len = Proc_Read(proc, &result, sizeof(result)); + Proc_Close(proc); + if (len == 0) + return; + + if (len != sizeof(result)) { + Log(LOG_CRIT, "Auth: Got malformed result!"); + Client_Reject(client, "Internal error", false); + return; + } + + if (result == true) { + Client_SetUser(client, Client_OrigUser(client), true); + (void)Login_User_PostAuth(client); + } else + Client_Reject(client, "Bad password", false); +} + +#endif + +/* -eof- */ diff --git a/src/ngircd/login.h b/src/ngircd/login.h new file mode 100644 index 0000000..6e3a21d --- /dev/null +++ b/src/ngircd/login.h @@ -0,0 +1,25 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 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 __login_h__ +#define __login_h__ + +/** + * @file + * Functions to deal with client logins (header) + */ + +GLOBAL bool Login_User PARAMS((CLIENT * Client)); +GLOBAL bool Login_User_PostAuth PARAMS((CLIENT *Client)); + +#endif + +/* -eof- */ diff --git a/src/ngircd/messages.h b/src/ngircd/messages.h index 90e0fdc..96ff2de 100644 --- a/src/ngircd/messages.h +++ b/src/ngircd/messages.h @@ -103,6 +103,7 @@ #define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels" #define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname" #define ERR_NOORIGIN_MSG "409 %s :No origin specified" +#define ERR_INVALIDCAP_MSG "410 %s %s :Invalid CAP subcommand" #define ERR_NORECIPIENT_MSG "411 %s :No recipient given (%s)" #define ERR_NOTEXTTOSEND_MSG "412 %s :No text to send" #define ERR_WILDTOPLEVEL "414 %s :Wildcard in toplevel domain" diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index 60d15a1..8a93bcb 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -498,7 +498,8 @@ Pidfile_Create(pid_t pid) len = snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid); if (len < 0 || len >= (int)sizeof pidbuf) { - Log( LOG_ERR, "Error converting pid"); + Log(LOG_ERR, "Error converting pid"); + close(pidfd); return; } @@ -642,12 +643,10 @@ NGIRCd_Init(bool NGIRCd_NoDaemon) } if (chroot(Conf_Chroot) != 0) { - if (errno != EPERM) { - Log(LOG_ERR, - "Can't change root directory to \"%s\": %s", - Conf_Chroot, strerror(errno)); - goto out; - } + Log(LOG_ERR, + "Can't change root directory to \"%s\": %s", + Conf_Chroot, strerror(errno)); + goto out; } else { chrooted = true; Log(LOG_INFO, diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c index 02ab893..66bfef5 100644 --- a/src/ngircd/parse.c +++ b/src/ngircd/parse.c @@ -36,6 +36,7 @@ #include "imp.h" #include "irc.h" +#include "irc-cap.h" #include "irc-channel.h" #include "irc-info.h" #include "irc-login.h" @@ -113,6 +114,7 @@ static COMMAND My_Commands[] = { "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 }, #endif #ifndef STRICT_RFC + { "CAP", IRC_CAP, 0xFFFF, 0, 0, 0 }, { "GET", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 }, { "POST", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 }, #endif diff --git a/src/ngircd/sighandlers.c b/src/ngircd/sighandlers.c index 427789c..efb41bc 100644 --- a/src/ngircd/sighandlers.c +++ b/src/ngircd/sighandlers.c @@ -218,8 +218,11 @@ Signal_Handler_BH(int Signal) break; #ifdef DEBUG case SIGUSR2: - if (NGIRCd_Debug) + if (NGIRCd_Debug) { + Log(LOG_INFO|LOG_snotice, + "Got SIGUSR2, dumping internal state ..."); Dump_State(); + } break; default: Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);