1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-09-23 20:54:02 +00:00

Compare commits

...

272 Commits

Author SHA1 Message Date
Alexander Barton
48fcb97fa4 New "Debian release" 21.1-0ab2 2014-07-14 12:01:46 +02:00
Alexander Barton
713fd3f883 Debian: Don't adjust path names that are correct by default
(cherry picked from commit f5944a17e4)
2014-07-14 11:41:28 +02:00
Alexander Barton
19da9a0801 Debian: Correctly set and use "docdir"
(cherry picked from commit 06920df4bb)
2014-07-14 11:14:08 +02:00
Alexander Barton
ee28e76df2 ngIRCd Release 21.1 2014-03-25 14:46:28 +01:00
Roy Sindre Norangshol
9a05c1145d Use server password when PAM is compiled in but disabled
(cherry picked from commit 485d0aec81)

Conflicts:
	src/ngircd/conf.c
2014-03-23 14:08:19 +01:00
Alexander Barton
a3ad2927cc doc/Platforms.txt: Update from master branch 2014-03-19 02:36:50 +01:00
Alexander Barton
6725f67cf1 Spoofed prefixes: Really kill connection on non-server links
This fixes commit 6cbe1308 which only killed the connection when the
spoofed prefix itself belonged to a non-server client.

(cherry picked from commit 5009ab3e8c)
2014-03-19 02:31:06 +01:00
Alexander Barton
c0c9b1b8ac Fix two K&R C portability issues
Fix the following two errors emitted by the Apple K&R C compiler
on Apple A/UX:

"./class.c", line 47: no automatic aggregate initialization
"./class.c", line 47: illegal lhs of assignment operator

"./conf.c", line 1052: syntax error

Tested on A/UX 3.1.1.

(cherry picked from commit a4ed90ba9a)
2014-03-19 02:30:22 +01:00
Alexander Barton
1d3137ff69 CHARCONV: Fix handling conversion errors
Don't overwrite already converted text!

(cherry picked from commit abf280d5bd)
2014-03-19 02:28:08 +01:00
Alexander Barton
d20de38161 Services.txt: Update information for Anope 2.x
(cherry picked from commit 755562d147)
2014-03-19 02:27:50 +01:00
Alexander Barton
9ecd8f616f Correctly use cloaked IRC masks on "INVITE nickname"
The cloaked IRC mask of a user is his visible mask, so the daemon has
to use it for generating the "one time" entries for the invite list of
the given channel.

Without this patch, ngIRCd records the real IRC mask which will never
match while the target client is "+x", and even worse, will disclose
the real mask on "MODE #channel +I" commands :-/

Bug reported by Cahata on #ngircd, thanks!

(cherry picked from commit 20b52fe33d)
2014-03-19 02:27:16 +01:00
Alexander Barton
4525425879 configure: Only link "contrib/Debian" if it exists
This isn't the case on "VPATH builds", for example.

(cherry picked from commit 14a84dfca5)
2014-03-19 02:26:39 +01:00
Alexander Barton
4286af08ce Use $(MKDIR_P) instead of $(mkinstalldirs) in Makefile's
And test for "mkdir -p" using AC_PROG_MKDIR_P in "configure".

(cherry picked from commit 90062111f7)
2014-03-19 02:25:54 +01:00
Alexander Barton
bb3096b0d3 Fix configure script and "make check" for TCP Wrappers
Add missing #include's and static variables.

Problem spotted on OpenBSD.

(cherry picked from commit e747fe9277)

Conflicts:
	configure.ng
	src/portab/portabtest.c
2014-03-19 02:25:21 +01:00
Alexander Barton
9f090d7554 Add libwrap at the end of the configure run
If libwrap becomes added earlier, other tests may fail because of not all
external variables required by libwrap are available when linking: for
example allow_severity and deny_severity.

This patch adds generic support for the LDFLAGS_END and LIBS_END variables
(CFLAGS_END has been implemented already).

Problem spotted on OpenBSD.

(cherry picked from commit 0f85c4c6a7)

Conflicts:
	configure.ng
2014-03-19 02:21:25 +01:00
Alexander Barton
ecb55704b7 platformtest.sh: don't use "test -e", it isn't portable
(cherry picked from commit e2b85ccde3)
2014-03-19 02:14:05 +01:00
Alexander Barton
9a11ab0d1b Makefile.am: don't use "test -e", it isn't portable
(cherry picked from commit 7b358a57ac)
2014-03-19 02:10:02 +01:00
Alexander Barton
f55d03c153 Update Copyright notices for 2014
(cherry picked from commit 788da901ee)
2014-03-19 02:08:19 +01:00
Federico G. Schwindt
b86da5ed9a Fix permanent k/gline
Reported by Toni Spets (hifi - at - jnz - dot - fi).

(cherry picked from commit 9230f2fff1)
2014-03-19 02:07:36 +01:00
Alexander Barton
d009df909b WEBIRC: Don't respect hostname when DNS is disabled
When DNS lookups are disabled, don't set the hostname received by the
WEBIRC command, but use the IP address instead.

Reported by Toni Spets <toni.spets@iki.fi>, thanks!

Closes bug #167.

(cherry picked from commit 1a628fff51)
2014-03-19 02:07:05 +01:00
Alexander Barton
74db76b792 OS X has a working getaddrinfo() implementation
(cherry picked from commit bd33bd770d)
2013-12-27 22:03:37 +01:00
Alexander Barton
21ef762109 Check for working getaddrinfo() function
At least AIX 4.3.3 and 5.1 have a broken implementation of getaddrinfo()
which doesn't handle "0" as numeric service correctly. This patch adds
a configure check for this case and changes all calling functions to only
use getaddrinfo() if it "works".

See <http://www.stacken.kth.se/lists/heimdal-discuss/2004-05/msg00059.html>

(cherry picked from commit b8433e9261)

Conflicts:
	configure.ng
2013-12-27 22:02:29 +01:00
Alexander Barton
e379a0881e Only use unsetenv() when it is available
AIX 4.3 dosn't support it, for example.

(cherry picked from commit ae00c100ac)
2013-12-27 21:56:07 +01:00
Alexander Barton
54a13350b1 conf-ssl.h: make code compatible with pre-ANSI C compilers
(cherry picked from commit 61d1c864c5)
2013-12-27 21:55:50 +01:00
Alexander Barton
3b46356ce2 vsnprintf.c: make code compatible with ansi2knr tool
(cherry picked from commit 8d25044ce5)
2013-12-27 21:55:27 +01:00
Alexander Barton
ac127ff20a Remove wrong #ifdef in Option_String()
This fixes the following error when compiling without zlib support:

  irc.c: In function ‘Option_String’:
  irc.c:487: error: ‘options’ undeclared (first use in this function)

Reported by "der_baer" on #ngircd.

(cherry picked from commit 4ab688c5e8)
2013-12-27 21:52:59 +01:00
Alexander Barton
94148c37f5 ngIRCd Release 21 2013-10-30 22:20:36 +01:00
Alexander Barton
f25be28ab8 doc/Platforms.txt: add Mac OS X 10.6.8 2013-10-30 22:13:21 +01:00
Alexander Barton
fae7bd1bb7 Update doc/Platforms.txt 2013-10-28 00:00:06 +01:00
Alexander Barton
0556aa1901 ngircd.init: Make sure no stale PID file is left over 2013-10-26 21:34:56 +02:00
Alexander Barton
48698f14a2 platformtest.sh/Platforms.txt: allow user names up to 8 characters 2013-10-23 20:47:55 +02:00
Federico G. Schwindt
8e6db769ac Check and call arc4random_stir() if present
FreeBSD prior to 10.0 does not automatically stir on fork(). Same with
current NetBSD. If arc4random_stir() is present assume is needed and
call it instead of srand().
2013-10-23 16:00:26 +01:00
Alexander Barton
8a041373bb Debian: Fix sed(1) rules adjusting "ngircd-full" package
Error introduced by last commit :-/
2013-10-20 18:33:22 +02:00
Alexander Barton
37c8699f34 Debian: Fix default "HelpFile" file name in ngircd.conf
The "full" package variants must use "/usr/share/doc/ngircd-full/Commands.txt"
and "/usr/share/doc/ngircd-full-dbg/Commands.txt" respectively.
2013-10-20 18:06:21 +02:00
Alexander Barton
788b3002d8 ngIRCd Release 21~rc2 2013-10-20 15:51:03 +02:00
Alexander Barton
beb9f65dc8 platformtest.sh: Detect clang compilers 2013-10-20 15:25:19 +02:00
Federico G. Schwindt
62865f7e19 Add support for longer config lines
With the introduction of CipherList we could have longer config lines.
Handle up to 1024 bytes and warn if the line will be truncated.
2013-10-17 22:10:53 +01:00
Federico G. Schwindt
a7dda1b28c Report the correct file on error 2013-10-17 21:52:15 +01:00
Alexander Barton
cba5a2579f doc/Platforms.txt: Add Open64 and tcc C compilers on Linux
Thanks to Götz Hoffart!
2013-10-16 22:27:40 +02:00
Alexander Barton
a2479bb906 platformtest.sh: Detect tcc compiler 2013-10-16 21:59:31 +02:00
Federico G. Schwindt
17589534d0 Add support for arc4random
If arc4random is present it will be used over the srand/rand interface.
This fixes some warnings in OpenBSD-current.
2013-10-16 16:32:06 +01:00
Federico G. Schwindt
ea26fd2840 Fix another strcat warning missed in commit 4c5b43 2013-10-16 10:41:40 +01:00
Alexander Barton
45d3e6aa91 platformtest.sh: Clean up GIT source tree, when possible 2013-10-14 23:47:16 +02:00
Alexander Barton
0bd3fb88b2 platformtest.sh: Detect Apple LLVM (clang) compiler 2013-10-14 23:45:59 +02:00
Alexander Barton
c34b91d8dd Update (date of) manual pages 2013-10-07 23:02:27 +02:00
Alexander Barton
56da86b4f4 ChnageLog file: even more spelling fixes ... 2013-10-07 22:17:49 +02:00
Alexander Barton
ea8a2bf1fc INSTALL file: Update "Upgrade Information" 2013-10-07 22:15:22 +02:00
Alexander Barton
1b349b05d5 Fix spelling in NEWS and ChangeLog files 2013-10-07 21:59:25 +02:00
Alexander Barton
4c5b439992 ngircd.c, main(): use strlcat() instead of strcat()
This fixes the following warning on OpenBSD 5.3:

 ngircd.o(.text+0xeb4): In function `main':
  src/ngircd/ngircd.c:300: warning: strcat() is almost always misused,
                                    please use strlcat()

Thanks to Götz Hoffart for reporting this!
2013-10-07 21:56:09 +02:00
Alexander Barton
86cd2da8d5 ngIRCd Release 21~rc1 2013-10-05 23:40:29 +02:00
Alexander Barton
9b1fee8995 Update NEWS and ChangeLog files 2013-10-02 02:10:48 +02:00
Alexander Barton
2798a12444 Actually KILL clients on GLINE/KLINE
Kill all clients that match a new GLINE/KLINE mask and genrate apropriate
KILL commands. These KILL commands can be superfluous, but are required
when the IRC Operator isn't allowd to set remote G-Lines or if there are
older servers in the network that don't kill clients on GLINE/KLINE.

Closes bug #156.
2013-10-01 12:26:34 +02:00
Alexander Barton
02182143c3 Don't forward KILL commands for unknown clients 2013-10-01 12:20:23 +02:00
Alexander Barton
b5faf3055b New function IRC_KillClient() to kill clients
The old local function Kill_Nick() in irc.c has been an ugly hack. This
patch implements a generic function for killing clients.

Adjust all callers of Kill_Nick() and respect the return code!
2013-10-01 12:13:17 +02:00
Alexander Barton
cccd8fc957 Adjust log messages for invalid and spoofed prefixes
Now invalid prefixes aren't logged no more when originating from an other
server (besides in debug mode), and spoofed prefixes are correctly logged
using LOG_WARNING (from an other server) or LOG_ERR (from a client) levels.

In addition, the log message texts have been adjusted to better reflect
what will happen: commands with invalid prefixes are ignored and logged,
commands with spoofed prefixes will result in the client being disconncted
(regular users) or the command being ignored (other servers).

This cleans up logging of commands related to already KILL'ed clients.
2013-09-26 02:28:16 +02:00
Alexander Barton
eccbd97e1f Remove CLIENT.oper_by_my, Client_SetOperByMe() and Client_OperByMe()
All places where Client_OperByMe() is used can either be converted to
Client_HasMode(Client, 'o') or Op_Check().

And Op_Check() itself can use the connection handle for deciding whether
the IRC Operator is a local user or not.
2013-09-25 01:29:23 +02:00
Federico G. Schwindt
ec5ab4fcd1 Add support to show user links using "STATS L"
Change "stats L" to show servers and user links and restrict it to
IRC Operators.
2013-09-24 21:17:35 +02:00
Alexander Barton
13a5358a3d Log an error (not info) when working directory can't be changed 2013-09-24 00:04:54 +02:00
Alexander Barton
99db111bca doc/PAM.txt: add a slightly more useful example 2013-09-19 00:17:43 +02:00
Federico G. Schwindt
27b9d32bf2 Change the certificate fingerprint digest to sha256
While here correct some indentation.
2013-09-17 17:35:56 +01:00
Federico G. Schwindt
0985d69cc6 Change cipher defaults
Switch cipher defaults to HIGH:!aNULL:@STRENGTH (OpenSSL) or
SECURE128 (GnuTLS).
2013-09-17 17:15:24 +01:00
Alexander Barton
d0977258ee Merge remote-tracking branch 'alex/bug162-SSLCipherList'
* alex/bug162-SSLCipherList:
  Cipher list selection for GnuTLS
  ConnSSL_Init_SSL(): correctly set CONN_SSL flag
  Cipher list selection for OpenSSL
  ConnSSL_InitLibrary(): Code cleanup
2013-09-16 17:32:25 +02:00
Federico G. Schwindt
2cebfc54f5 Fix server reconnection
In some error cases conn_id will be left as SERVER_WAIT and
subsequently ignored in Check_Servers(). Ensure conn_id is set to
NONE before returning from New_Server() if we couldn't establish
the connection.

Prompted by a report from gabrielgi-at-gmail-dot-com.
2013-09-16 02:15:49 +01:00
Alexander Barton
de3e5fa77c Don't ignore SSL-related errors during startup
Without this patch, ngIRCd ignores SSL-related messages and continues
to start up but only listens on plain text communication ports -- and
this most probably isn't what the administrator wanted ...

Closes bug #163.
2013-09-16 00:31:03 +02:00
Alexander Barton
b9006acee3 Cipher list selection for GnuTLS
This patch implements the missing functionality for cipher list selection
using GnuTLS (our OpenSSL code has this already).
2013-09-15 17:57:47 +02:00
Alexander Barton
51231ac8d4 ConnSSL_Init_SSL(): correctly set CONN_SSL flag
The CONN_SSL flag must be set before any calls to ConnSSL_Free()!
2013-09-15 17:35:52 +02:00
Alexander Barton
84ed46d4c1 Cipher list selection for OpenSSL
This patch introduces the possibility to arbitrarily select ciphers which
should be promoted resp. declined when establishing a SSL connection
with a client by implementing the new configuration option "CipherList".

By default, OpenSSL would accept low and medium strength and RC-4 ciphers,
which nowadays are known to be broken.

This patch only implements the feature for OpenSSL. A GnuTLS counterpart
has to be implemented in another patch ...

Original patch by Bastian <bastian-ngircd@t6l.de>.

Closes bug #162.
2013-09-15 15:09:36 +02:00
Alexander Barton
849f85a05c ConnSSL_InitLibrary(): Code cleanup 2013-09-15 14:09:31 +02:00
Alexander Barton
e8e0351985 TRACE: fix error message when there are too many parameters
ircd 2.11 ignores additional parameters silently, but I don't think
that this is the correct behaviour either ...
2013-09-07 00:19:21 +02:00
Alexander Barton
131364def1 IRC_SetPenalty(): Code cleanup 2013-09-07 00:05:49 +02:00
Federico G. Schwindt
bcb45da1b4 Add more penalty times
Ensure before every numeric 461 there is a call to IRC_SetPenalty().
2013-09-06 23:02:01 +01:00
Federico G. Schwindt
08f9d31d60 Rework check for number of parameters
Move most of the checks that return numeric 461 into Handle_Request().
2013-09-06 23:01:59 +01:00
Federico G. Schwindt
37609d6a4f Reorder checks
Move oper and Conf_MorePrivacy checks after checking the number of
parameters.
2013-09-05 17:31:57 +01:00
Federico G. Schwindt
33c2d5e4e2 Move the IRC_SetPenalty() call after the asserts 2013-09-05 17:31:57 +01:00
Federico G. Schwindt
a98bbc8e0b Correct numeric returned by whois
As per RFC whois should return 431 if no nick is provided.  While
here convert upper check to use irc-macros. As a bonus we get to set
the penalty for free.
2013-09-05 17:31:56 +01:00
Federico G. Schwindt
9f74c0ff07 Minor cosmetic change
Add a define to indicate any client.  While I'm here use hex values
instead of decimal, it's somewhat clearer that they could be OR'ed
together.
2013-09-05 17:31:55 +01:00
Alexander Barton
e5cdd61fe3 Commands.txt: Document proprietary DIE <message> parameter 2013-09-05 00:19:03 +02:00
Alexander Barton
e3a2a6c44d getpid.sh: use /bin/pidof when available 2013-09-03 21:33:22 +02:00
Alexander Barton
aad92ceafe Don't enforce channel types for other servers
The configuration option "AllowedChannelTypes" must only be enforced for
regular clients and not for remote servers. Channels created by other
servres are always allowed, because they already exist and the daemon
must stay in sync with the network.
2013-09-03 17:13:46 +02:00
Alexander Barton
4102e8fdfe Only log "IDENT ... no result" when IDENT was looked up
Without this patch, ngIRCd logged the "IDENT lookup for connection X:
no result"-message even when IDENT lookups have been disabled using the
"Ident = no" configuration option, which is a little bit misleading.

Reported by "btwe" in #ngircd.
2013-09-02 16:42:20 +02:00
Florian Westphal
f8f8a9a041 ngircd: use setgid/setuid errno value in error path
Need to use saved errno value as strerror argument, else you
get bogus output ('success') in the log message.
2013-08-31 22:42:56 +02:00
Alexander Barton
04b947cdc3 Show connection flag "s" (SSL) in RPL_TRACE{LINK|SERVER}
Now you can check if a server-to-server link is SSL-encrypted or not
using the IRC "TRACE" command.

Idea by Götz Hoffart, thanks!
2013-08-31 14:15:24 +02:00
Federico G. Schwindt
be2e611680 Change away to be allocated dynamically 2013-08-27 00:06:03 +01:00
Alexander Barton
41f75b6974 Ignore "operation not permitted" while dropping groups
Without this exception, you can't start ngIRCd as user any more,
it is analog to setting the user and group ID.
2013-08-27 00:41:36 +02:00
Florian Westphal
e009ccbe66 ngircd: discard supplementary group ids on startup
The intention was to switch to JUST uid:gid, but setgid is not
sufficient.

Reported-by:  Michael Scherer <misc@zarb.org>
2013-08-27 00:19:31 +02:00
Alexander Barton
46d43dc09c Xcode: update project settings for Xcode 5 2013-08-26 23:23:12 +02:00
Alexander Barton
44698e44e8 Merge branch 'bug159-WebircIPA'
* bug159-WebircIPA:
  Introduce Free_Client() function to free CLIENT structure
  Save client IP address text for "WebIRC" users
2013-08-26 23:22:20 +02:00
Alexander Barton
0ff33777fe Introduce Free_Client() function to free CLIENT structure 2013-08-26 22:55:00 +02:00
Alexander Barton
1dc93286a0 Save client IP address text for "WebIRC" users
This patch introduces a new field in the CLIENT structure, "ipa_text",
which points to an optional textual representation of the client IP
address (or NULL) which can be used to store the "real" IP address
information of a client using the "WEBIRC" protocol.

Without this patch, ngIRCd ignored the <ip-address> paramater ...

In addition, the functions Client_SetIPAText() and Client_IPAText()
have been introduced to set and get the textual representation of the
client IP address.

Client_IPAText() can be used even when no "IP address text" has been
set before, it then returns the real IP address of the connection.

Closes bug #159.
2013-08-26 22:54:00 +02:00
Alexander Barton
2bacb8210b Implement new configuration option "DefaultUserModes"
The new configuration option "DefaultUserModes" 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, you can't set "a" (away) or "o" (IRC Op), for example! User
modes "i" (invisible) or "x" (cloaked) etc. are "interesting", though.

Default: set no modes (like without this patch).

Closes bug #160.
2013-08-26 21:17:10 +02:00
Federico G. Schwindt
3b65f4e38d Change strdup() to strndup() 2013-08-26 12:18:46 +01:00
Federico G. Schwindt
6ac5a82eec private strndup() implementation in case libc does not provide it 2013-08-26 10:47:04 +01:00
Federico G. Schwindt
086cf3a272 Cosmetic changes to METADATA
Update certfp and sort entries.
2013-08-25 05:26:08 +01:00
Federico G. Schwindt
8d01be7bbd Silence warning
Cast the result of the operation to long, not the time(NULL) call.
On systems where sizeof(time_t) is other than long this will produce
a warning.
2013-08-25 05:24:11 +01:00
Federico G. Schwindt
eb86d234f8 Plug memory leak 2013-08-25 05:24:11 +01:00
Federico G. Schwindt
3af0ece2bc Implement account login support
This is done via the `accountname' METADATA command and used to
automatically identify users after netsplits or across service
restarts.
2013-08-25 05:24:08 +01:00
Federico G. Schwindt
a9ffbdea3f Fix spelling 2013-08-24 17:51:44 +01:00
Alexander Barton
6dc5471a75 ngIRCd Release 20.3
(cherry picked from commit bb6e277963)

Conflicts:
	ChangeLog
	NEWS
2013-08-23 23:34:55 +02:00
Alexander Barton
309122017e Correctly handle return code of Handle_Write()
There have been code paths that ignored the return code of Handle_Write()
when sending "notice auth" messages to new clients connecting to the
server. But because Handle_Write() would have closed the client connection
again if an error occurred, this would have resulted in new errors and
assert()'s later on that could have crashed the server (denial of service).

Only setups having the configuration option "NoticeAuth" enabled are
affected, which is not the default.

CVE-2013-5580.
2013-08-23 21:40:51 +02:00
Alexander Barton
8f530eb315 Enhance log messages on "recursive" connection errors 2013-08-21 01:16:16 +02:00
Alexander Barton
d56341c77b Add some assert() calls to ng_ipaddr library 2013-08-21 00:23:47 +02:00
Alexander Barton
212d99146d Update ChangeLog file 2013-08-20 13:08:43 +02:00
Alexander Barton
e2f09213bc Debian init script: test for binary after reading defaults
This allows the system administrator to overwrite the DAEMON variable in
/etc/defaults/<name> and to use this init script even when the default
"/usr/sbin/ngircd" doesn't exist on the system.
2013-08-19 23:33:11 +02:00
Alexander Barton
c8b12af1d2 Merge branch 'ssl-log-messages'
* ssl-log-messages:
  Make SSL-related log messages more readable
  ConnSSL_HandleError: Code cleanup, more documentation
2013-08-17 22:05:59 +02:00
Alexander Barton
a919e02ba1 Make SSL-related log messages more readable
- Don't use internal function names but describe the error.
 - Streamline wording, use "SSL" for SSL and TLS.
 - Streamline punctuation.
2013-08-14 10:56:09 +02:00
Federico G. Schwindt
b081cfb628 Use _IRC_ARGC_BETWEEN_OR_RETURN_ when possible 2013-08-14 00:07:12 +01:00
Alexander Barton
dd4c60cf39 ConnSSL_HandleError: Code cleanup, more documentation 2013-08-13 00:09:04 +02:00
Alexander Barton
4828bae8d3 Change log level of "SSL connection shutting down" 2013-08-12 00:02:40 +02:00
Federico G. Schwindt
cd38e9580e Fix 2 bugs introduced in 74514b8c23
Channel_Modes() and Channel_Topic() return static memory that is zeroed at
creation time. Fix checking for empty modes and topic so they're propagated
correctly.
2013-08-11 20:57:11 +01:00
Alexander Barton
aeebde4642 configure: Don't quote IO backend type(s)
It's not needed and inconsistent compared to the other settings.

Reported by "allerbest" (Götz Hoffart) on #ngircd, thanks!
2013-08-11 11:40:48 +02:00
Alexander Barton
298158501d IRC_SERVER(): Code cleanup 2013-08-07 00:13:08 +02:00
Alexander Barton
904c8a4375 Introduce new function IRC_WriteErrClient()
This function is used to send "error messages", including numerics,
back to clients and to automatically enforce a 2 second penalty. With
this patch, all error results enforces a delay for the client.

All callers of IRC_WriteStrClient(ERR_xxx) have been converted.

Please note that this patch prolongs the time "make check" needs
to complete its tests, because of lots of new enforced penalties ...
2013-08-07 00:10:50 +02:00
Alexander Barton
b86e33ef49 irc-macros.h: Update copyright, don't forget contributors! 2013-08-06 23:36:16 +02:00
Alexander Barton
0a3d8d60d3 irc-write.c: Clean up code and add more documentation comments 2013-08-06 23:21:48 +02:00
Alexander Barton
08d49a8fa0 Fix return code of some IRC_WriteXXX() functions
These functions usually write to more than one target, and therefore
can't return value indicating success or failure in a sane way. And, even
more omportant, these functions should send to as much as possible clients
and not stop at the first client which isn't reachable any more!
2013-08-06 23:18:57 +02:00
Alexander Barton
8f5cbe51a7 Streamline punctuation of log messages
See commit d38d153f for details.
2013-08-06 21:34:32 +02:00
Alexander Barton
bd0de15d31 Update NEWS and ChangeLog files 2013-08-06 21:14:56 +02:00
Federico G. Schwindt
fcdb5cf8dd More spelling corrections 2013-08-05 11:06:52 +01:00
Federico G. Schwindt
7db8481500 Inline who_flags_status 2013-08-05 11:05:12 +01:00
Federico G. Schwindt
74514b8c23 Convert more code to use Channel_HasMode 2013-08-04 21:16:03 +01:00
Federico G. Schwindt
c74115f25c Simplify mode checking on channels and users within a channel
Add Channel_HasMode() and Channel_UserHasMode() and use it where
possible.
2013-08-04 18:28:04 +01:00
Federico G. Schwindt
672a167963 Use Client_HasMode and Client_HasFlag where appropriate 2013-08-04 17:25:24 +01:00
Alexander Barton
139f5961a0 Merge branch 'bug152-AllowedChannelTypes'
* bug152-AllowedChannelTypes:
  Implement new configuration option "AllowedChannelTypes"
  Introduce "CHANTYPES" #define
2013-08-04 14:11:12 +02:00
Alexander Barton
5258fb7f7c Implement new configuration option "AllowedChannelTypes"
The new configuration variable "AllowedChannelTypes" 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 patch deprecates the "PredefChannelsOnly" variable, too, but it is
still supported and translated to the apropriate "AllowedChannelTypes"
setting. When "PredefChannelsOnly" is processed, a warning message is
logged.

Closes bug #152.
2013-08-04 14:10:12 +02:00
Federico G. Schwindt
15dfdaac82 More spelling fixes
Remove superflous comments, mostly in German. Fix spelling and
use american variants for consistency.
2013-08-04 12:45:11 +01:00
Federico G. Schwindt
bb8d207efa Change cloaked hostname to be malloc'd on demand
This shaves a few bytes when cloaked hostnames are not used and
restricts the cloakhost announcement iif there is something to
send.
2013-08-04 10:15:11 +01:00
Federico G. Schwindt
e03d8eb728 Add Client_HasFlag() to check if a client has certain flag 2013-08-04 04:00:34 +01:00
Federico G. Schwindt
a95d3e05e7 Fix spelling 2013-08-04 03:15:27 +01:00
Federico G. Schwindt
646a97de5f Rename XXX_Fingerprint to XXX_CertFp 2013-08-04 03:14:27 +01:00
Federico G. Schwindt
8e60fac73b Improved client announcement
Move Announce_User() to client.c and rename it to Client_Announce().
Use this in cb_introduceClient() instead of duplicating the code.
This fix the certificate fingerprint announcement for new clients.
Also ensure the certificate fingerprint is only announced if the
client supports it (`M' flag).
2013-08-04 00:22:38 +01:00
Alexander Barton
5e775a3fae Introduce "CHANTYPES" #define
This #define lists all the prefix characters of all supported channel
types, this is "#&+" at the moment.
2013-08-04 00:35:08 +02:00
Alexander Barton
69ce65bacb Merge remote-tracking branch 'fgsch/certfp'
* fgsch/certfp:
  Simplify MOTD handling
  Add certificate fingerprint support
2013-08-03 00:29:12 +02:00
Federico G. Schwindt
bf8e03c466 Simplify MOTD handling
Merge Show_MOTD_Start, Show_MOTD_Sendline and Show_MOTD_End into
IRC_Show_MOTD.
2013-08-02 23:24:18 +01:00
Federico G. Schwindt
1254d315b9 Add certificate fingerprint support 2013-08-02 23:24:06 +01:00
Alexander Barton
4ec19c0332 Update irc-server.c to use irc-macros.h
And add some comments :-)
2013-08-03 00:00:47 +02:00
Alexander Barton
61a6691b36 Commands.txt: Update more descriptions
Update description of "CHANINFO", "METADATA", "NJOIN", "SERVER", "SQUIT",
"GET", and "POST".
2013-08-02 23:59:32 +02:00
Alexander Barton
78c8212280 Update irc-oper.c to use irc-macros.h 2013-08-02 23:27:11 +02:00
Alexander Barton
adc8d4f6c8 Commands.txt: Update more descriptions
Update description of "CONNECT", "DIE", "DISCONNECT", "GLINE", "KILL",
"KLINE", "OPER", "REHASH", "RESTART" and "WALLOPS".
2013-08-02 23:25:23 +02:00
Alexander Barton
24183b1a91 Commands.txt: Fix <target> description of TRACE command 2013-08-02 02:16:21 +02:00
Alexander Barton
888c524683 Update irc-mode.c to use irc-macros.h
This includes code cleanups and more comments, too.
2013-08-02 01:48:35 +02:00
Alexander Barton
ae0af66d50 Update irc-channel.c to use irc-macros.h
This includes code cleanups, too :-)
2013-08-02 01:46:57 +02:00
Alexander Barton
a8ecde2553 Commands.txt: Update more descriptions
Update descriptions of "AWAY", "JOIN", "LIST", "MODE", "PART",
"TOPC", and "TRACE".
2013-08-02 01:45:02 +02:00
Alexander Barton
fef10f590b Commands.txt: Streamline references to IRC+ protocol 2013-08-02 01:42:40 +02:00
Alexander Barton
771e539c18 Show IRC Operator name when logging a successful OPER command 2013-08-01 00:24:10 +02:00
Alexander Barton
313881d0c1 Add penalty times in error paths of generic IRC helper macros
Add a 2 second penalty time when the number of parameters is invalid.
2013-07-30 22:08:04 +02:00
Alexander Barton
3bd973037a Add more penalty times in error paths
This patch changes the handlers of the "PASS", "NICK", "USER",
and "SERVICE" commands to enforce a 2 second penalty when an error
like "need more/other parameters" occurs.

More functions should follow, I think ...
2013-07-30 22:05:00 +02:00
Alexander Barton
f494023b0d Update irc-login.c to use irc-macros.h
This includes code cleanups, too :-)
2013-07-30 21:18:42 +02:00
Alexander Barton
659d126460 Commands.txt: Update more descriptions
Update descriptions of "NICK", "PASS", "PING", "PONG", "QUIT", "USER",
"WEBIRC", "SERVICE", and "SVSNICK".
2013-07-30 21:12:24 +02:00
Alexander Barton
76dcb08266 Commands.txt: Update description of "PRIVMSG", "NOTICE", and "SQUERY" 2013-07-19 18:16:12 +02:00
Alexander Barton
4cb2edf020 Add "compile" to .gitignore file 2013-07-18 23:43:12 +02:00
Alexander Barton
720eb874a9 Commands.txt: Update description of the "ERROR" command 2013-07-18 23:42:00 +02:00
Alexander Barton
fa15eb1698 Update irc.c to use irc-macros.h
This includes code cleanups and better documentation for some
functions, too.
2013-07-18 23:35:33 +02:00
Alexander Barton
b54e664a63 Merge pull request #4 from fgsch/master
Changes for ngircd 21.
2013-07-18 13:38:19 -07:00
Federico G. Schwindt
7adc4b8e99 Handle services in IRC_WHOIS_SendReply()
If the target is a service, advertise it as such and ignore operator mode.
2013-07-18 19:52:17 +01:00
Federico G. Schwindt
5021977bb1 Fix spelling 2013-07-18 17:51:02 +01:00
Alexander Barton
5115756b79 Slightly update ngircd.8 manual page 2013-07-17 14:36:54 +02:00
Alexander Barton
f6ac0d89ae Travis-CI: Enable OpenSSL and libiconv support 2013-06-04 12:46:44 +02:00
Alexander Barton
11240376a5 Updated NEWS and ChangeLog files 2013-06-04 11:42:25 +02:00
Alexander Barton
e377f4ea47 Enhance Travis-CI configuration file
It now configures the sandbox to build ngIRCd with IPv6, IDENT, PAM,
TCP-Wrappers, and zlib support. And it installs expect(1) and telnet(1)
for the test suite.
2013-06-04 11:36:08 +02:00
Alexander Barton
9d3800fd15 Merge pull request #3 from Cofyc/master
irc-info.c: some commands use LINE_LEN as command buffer len
2013-05-30 08:55:48 -07:00
Yecheng Fu
4f525d39d4 LINE_LEN -> COMMAND_LEN
LINE_LEN is configuration file line length
2013-05-30 13:53:33 +08:00
Alexander Barton
7ea3864a93 IncludeDir: default to "$SYSCONFDIR/ngircd.conf.d"
Now "IncludeDir" defaults to "$SYSCONFDIR/ngircd.conf.d" instead
of no directory, but a missing directory is only reported as an
error if it has explicitely configured in the main configuration
file and simply ignored otherwise.

Therefore it is now possible not to touch the default (sample)
configuration file at all, and set all distribution and/or system
specific configuration options in "*.conf" files stored in
"$SYSCONFDIF/ngircd.conf.d/".

Thanks to "Elmasloco" for the idea!
2013-05-25 00:25:38 +02:00
Alexander Barton
891dbd2acc "IncludeDir" can't be overwritten by included files 2013-05-24 22:40:23 +02:00
Alexander Barton
f206fda8ae Implement new configuration option "IncludeDir"
The option "IncludeDir" in the [Options] section can be used
to specify a directory which can contain further configuration
files and configuration file snippets matching the pattern
"*.conf" that should be read in after the main configuration
file ("ngircd.conf" by default) has been parsed.

Closes bug #157.
2013-05-24 22:34:53 +02:00
Alexander Barton
6beb0fad3f conf.c: New function Read_Config_File()
This function reads in and parses a single configuration file.
Adjust all other functions to display the correct name of the
file being read in currently.
2013-05-24 21:57:42 +02:00
Alexander Barton
27fd92d580 Rename "Mask" variables into "Pattern" in assert() statements
This completes commit 3ab00e3a11 which broke debug builds.
2013-04-21 15:58:46 +02:00
Federico G. Schwindt
51e5ba94b3 Ensure there is enough space for the mask
As pointed by Alex while strl{cat,cpy} take the full length
we need to leave space to ensure a proper mask is always created
so revert the removal of - N from my last change.
2013-04-20 10:53:16 +01:00
Federico G. Schwindt
b4d0a40383 Better description for Lists_CheckReason() 2013-04-20 00:44:05 +01:00
Federico G. Schwindt
3ab00e3a11 Change Lists_MakeMask() to receive a buffer for the mask
Change callers accordingly so they don't rely on a global buffer and
rename Mask to Pattern where it makes sense since some functions
where indeed receiving a pattern and not a mask.
2013-04-20 00:43:47 +01:00
Federico G. Schwindt
cde2e8a277 Fix use-after-free on Lists_CheckReason()
Change Lists_CheckReason() to receive a buffer where the reason
will be stored and its length.  Change callers accordingly.

Change Class_GetMemberReason() (and its callers) in a similar way
so it doesn't rely on a global buffer for the rejected reason.
2013-04-20 00:43:35 +01:00
Alexander Barton
528c8fc244 Update doc/Platforms.txt a little bit ... 2013-04-01 17:23:49 +02:00
Alexander Barton
7f9bce705c Build OS X package with correct file permissions
This requires to have the correct permissions in the source tree, which
is "root:wheel", which in turn requires root privileges. Therefore the
Makefile now tries to become root on "make osxpkg-dest" but tries hard
not to require root privileges on "clean" etc.
2013-03-27 13:11:30 +01:00
Alexander Barton
ce3e41cf4c Xcode: fix detection of host OS, vendor, and CPU 2013-03-27 12:47:12 +01:00
Alexander Barton
dd6a058992 PackageMaker: use relativ path names 2013-03-27 12:46:07 +01:00
Alexander Barton
7ed06b2189 Add Travis-CI configuration file 2013-03-25 15:24:47 +01:00
Alexander Barton
a14eb495b7 Make configure[.ng] compatible with autoconf 1.10 again
The incompatibility has been introduced by commit d0c9f4a6,
"configure: search for iconv_open as well as libiconv_open".
2013-03-24 16:39:15 +01:00
Sebastian Köhler
0131e1e00b Lists_CheckReason(): Check for Client_MaskCloaked()
Look for possible cloaked Masks in Lists. Users with +x usermode can be
banned with their cloaked hostname now.
2013-03-20 03:40:31 +01:00
Alexander Barton
8618e942e6 Services.txt: Anope 1.9.8 has been released now 2013-03-13 22:08:16 +01:00
Alexander Barton
2fea782efc Commands.txt: Update description of the "KILL" command 2013-03-09 18:00:49 +01:00
Alexander Barton
a2e26aad1e Conn_Handler(): Don't test for penalty times
The Conn_Handler() main loop calls Handle_Buffer() which checks for the
"penalty time" of each client itself, so don't do it twice.
2013-03-09 17:58:10 +01:00
Alexander Barton
b4393277ea Don't read SSL client data before DNS resolver is finished
Fix the cb_clientserver_ssl() callback function to not read in and store SSL
encrypted client data before the asynchronous DNS resolver sub-process has
finished: This 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!
2013-03-09 17:44:34 +01:00
Alexander Barton
b33da9b8f3 Increase password length limit to 64 characters
Closes bug #154.
2013-03-08 19:31:57 +01:00
Alexander Barton
3e35857080 doc/Services.txt: Update Anope status and URL 2013-02-26 09:38:27 +01:00
Alexander Barton
b25fd8a98c Commands.txt: Update description of the "KICK" command 2013-02-24 18:53:33 +01:00
Alexander Barton
be08349dcb Commands.txt: Update description of the "INVITE" command 2013-02-24 18:53:10 +01:00
Alexander Barton
3228f1b267 irc-op.c: use irc-macros.h 2013-02-24 18:51:54 +01:00
Alexander Barton
a53de63ba7 irc-cap.c: use irc-macros.h 2013-02-24 18:51:43 +01:00
Alexander Barton
e8f512bfe7 irc-op.c: Update source code documentation 2013-02-24 18:50:12 +01:00
Alexander Barton
bb31d7b88c irc-cap.c: Update source code documentation 2013-02-24 18:49:07 +01:00
Alexander Barton
7f99f7c14f Add new _IRC_ARGC_EQ_OR_RETURN_ macro to irc-macros.h 2013-02-24 16:20:27 +01:00
Alexander Barton
883a8fa6f1 Add new _IRC_ARGC_BETWEEN_OR_RETURN_ macro to irc-macros.h 2013-02-24 16:14:13 +01:00
Alexander Barton
a7b04ce6cf irc-cap.c: move static functions to the top of the file
And remove now unnecessary (local) prototypes.
2013-02-24 16:08:17 +01:00
Alexander Barton
bd1b727187 Update Doxygen configuration 2013-02-22 18:11:26 +01:00
Alexander Barton
19d6f4740e Clean up Xcode project file, remove outdated files, add missing 2013-02-22 15:21:45 +01:00
Alexander Barton
0f0f4f41b8 src/testsuite/README: add whois-test.e 2013-02-22 15:21:45 +01:00
Alexander Barton
221365d8ef irc-login.c: conenction -> connection
Introduced by commit d3ef2239 as of Sun Jan 16 2011 ...
Thanks to Patrik Schindler <poc@pocnet.net> for reporting this!
2013-02-22 15:15:27 +01:00
Alexander Barton
2c96966431 Merge branch 'bug151-iconv' into master
* bug151-iconv:
  configure: search for iconv_open as well as libiconv_open
2013-02-15 21:59:28 +01:00
Alexander Barton
65359ff8f7 Merge branch 'bug153-ServerMask' into master
* bug153-ServerMask:
  Update irc-info.c to use irc-macros.h
  Add new irc-macros.h to project
  irc-info.c: add/streamline function documentation comments
  irc-info: move static functions at the top of the file
  Implement new function Client_SearchServer()

Conflicts:
	src/ngircd/irc-info.c
2013-02-15 21:59:06 +01:00
Alexander Barton
d0c9f4a692 configure: search for iconv_open as well as libiconv_open
On some installations iconv_open() is actually libiconv_open().
iconv_open() is the glibc version while libiconv_open() is the libiconv
version. This patch enables ngIRCd to detect both cases.

Tested on OpenBSD 5.1.

Closes bug #151.
2013-02-15 21:32:08 +01:00
Alexander Barton
d5763937ad configure: conversation -> conversion 2013-02-15 21:26:47 +01:00
Alexander Barton
25b19e08e2 ngIRCd Release 20.2
(cherry picked from commit c45d9dd1f0)
2013-02-15 12:48:10 +01:00
Sebastian Köhler
0e63fb3fa7 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.
2013-02-15 10:21:58 +01:00
Alexander Barton
3e72331896 sighandlers.c: Update some log messages 2013-02-13 00:27:05 +01:00
Alexander Barton
1438771124 my_sd_listen_fds(): really return an "int"
This fixes the following warning using Apple LLVM version 4.2
(clang-425.0.24) on OS X:

  src/ngircd/conn.c:157:9: Implicit conversion loses integer
                           precision: 'long' to 'int'
2013-02-11 23:25:13 +01:00
Alexander Barton
b95dfb3ffd Merge branch 'bug155-allowAtInUser'
* bug155-allowAtInUser:
  Allow "@" character in user names for authentication
2013-02-11 13:58:30 +01:00
Alexander Barton
4b15f10fbb Allow "@" character in user names for authentication
The "@" character isn't allowed in IRC usernames, because it is the
separator between user name and hostname in IRC masks:

  <nickname>!<username>@<hostname>

This patch 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.
2013-02-11 13:57:54 +01:00
Alexander Barton
628c14d656 Merge branch 'systemd'
* systemd:
  ngircd.sock: explicitely bind to IPv4 and IPv6 addresses
  Show address and port of sockets passed-in by systemd(8)
  Check type of sockets passed-in by systemd(8)
  Adjust severity levels of some log messages
  New configuration option "IdleTimeout": exit daemon when idle
  Implement support for systemd(8) "socket activation"
  contrib/README: add more files
2013-02-10 20:43:56 +01:00
Alexander Barton
2cb7023e28 ngircd.sock: explicitely bind to IPv4 and IPv6 addresses 2013-02-10 20:37:55 +01:00
Alexander Barton
69c3f96998 Show address and port of sockets passed-in by systemd(8) 2013-02-10 20:21:53 +01:00
Alexander Barton
5c6875d768 Check type of sockets passed-in by systemd(8)
This patch makes sure that ngIRCd doesn't try to handle sockets of
unsupported types, for example of AF_INET6 sockets when ngIRCd isn't
compiled with support for IPv6 ...
2013-02-10 20:20:58 +01:00
Alexander Barton
a78c7b3898 Adjust severity levels of some log messages 2013-02-10 20:18:44 +01:00
Alexander Barton
ac32d07aaf Commands.txt: spelling fixes ... 2013-02-10 00:35:03 +01:00
Alexander Barton
7fce719142 Merge branch 'HelpText'
* HelpText: (22 commits)
  Commands.txt: Update description of the "USERS" command
  Commands.txt: Update description of the "SUMMON" command
  Commands.txt: Update description of the "SERVLIST" command
  Commands.txt: Update description of the "WHOWAS" command
  Commands.txt: Update description of the "WHOIS" command
  Commands.txt: Update description of the "WHO" command
  Commands.txt: Update description of the "VERSION" command
  Commands.txt: Update description of the "USERHOST" command
  Commands.txt: Update description of the "TIME" command
  Commands.txt: Update description of the "STATS" command
  Commands.txt: Update description of the "NAMES" command
  Commands.txt: Update description of the "MOTD" command
  Commands.txt: Update description of the "LUSERS" command
  Commands.txt: Update description of the "LINKS" command
  Commands.txt: Update description of the "ISON" command
  Commands.txt: Update description of the "INFO" command
  Commands.txt: Update description of the "ADMIN" command
  Commands.txt: Add description for the "CHARCONV" command
  Commands.txt: Add description for the "CAP" command
  Commands.txt: Import descriptions from "rbose/command_help"
  ...
2013-02-10 00:29:30 +01:00
Alexander Barton
cb7e4e8679 Commands.txt: Update description of the "USERS" command 2013-02-10 00:25:19 +01:00
Alexander Barton
35452b3157 Commands.txt: Update description of the "SUMMON" command 2013-02-10 00:25:09 +01:00
Alexander Barton
e90d30a2cc Commands.txt: Update description of the "SERVLIST" command 2013-02-10 00:24:52 +01:00
Alexander Barton
45ab73ac81 Commands.txt: Update description of the "WHOWAS" command 2013-02-10 00:24:34 +01:00
Alexander Barton
78978994df Commands.txt: Update description of the "WHOIS" command 2013-02-10 00:24:14 +01:00
Alexander Barton
19cb29da51 Commands.txt: Update description of the "WHO" command 2013-02-10 00:23:59 +01:00
Alexander Barton
6ed3b6f85c Commands.txt: Update description of the "VERSION" command 2013-02-10 00:23:43 +01:00
Alexander Barton
5b8f13a4a9 Commands.txt: Update description of the "USERHOST" command 2013-02-10 00:23:27 +01:00
Alexander Barton
b6e6e2e1da Commands.txt: Update description of the "TIME" command 2013-02-10 00:23:10 +01:00
Alexander Barton
7c7fc8b5c4 Commands.txt: Update description of the "STATS" command 2013-02-10 00:22:50 +01:00
Alexander Barton
1a5e08f3f6 Commands.txt: Update description of the "NAMES" command 2013-02-10 00:22:24 +01:00
Alexander Barton
e051ea06fc Commands.txt: Update description of the "MOTD" command 2013-02-10 00:20:41 +01:00
Alexander Barton
a7023113e7 Commands.txt: Update description of the "LUSERS" command 2013-02-10 00:20:19 +01:00
Alexander Barton
02e24f5d1e Commands.txt: Update description of the "LINKS" command 2013-02-10 00:19:59 +01:00
Alexander Barton
13740c1bf4 Commands.txt: Update description of the "ISON" command 2013-02-10 00:19:41 +01:00
Alexander Barton
8212b730c7 Commands.txt: Update description of the "INFO" command 2013-02-10 00:19:20 +01:00
Alexander Barton
a4daa613ae Commands.txt: Update description of the "ADMIN" command 2013-02-10 00:18:43 +01:00
Alexander Barton
5dce3301bd Update irc-info.c to use irc-macros.h
This includes:

 - move IRC_SetPenalty() at the beginning of the handler functions,
 - use macros provided by irc-macros.h,
 - code cleanup.

The main benefits of this patch are core size reduction, streamlined
structure of the handler functions, and enhanced functionality:
because of the _IRC_GET_TARGET_SERVER_OR_RETURN_() macro using the
Client_SearchServer() function, the target of the specific IRC command
can now be given server names, server mask, or the nickname of a user
connected to the server.

Closes bug #153.
2013-02-09 23:58:11 +01:00
Alexander Barton
a917514546 Add new irc-macros.h to project
This file prvides some macros for common tasks required by functions
implementing handlers for IRC commands:

 * _IRC_ARGC_LE_OR_RETURN_
 * _IRC_ARGC_GE_OR_RETURN_
 * _IRC_GET_SENDER_OR_RETURN_
 * _IRC_GET_TARGET_SERVER_OR_RETURN_
2013-02-09 23:55:42 +01:00
Alexander Barton
4dc940f59e irc-info.c: add/streamline function documentation comments
Add missing comments, streamline wording, and remove references to the
RFCs: this will be added to ./doc/Commands.txt with an other patch and
we want to avoid redundancy ...
2013-02-09 23:33:29 +01:00
Alexander Barton
5facf5c15e irc-info: move static functions at the top of the file 2013-02-09 23:18:49 +01:00
Alexander Barton
1e8b775a7a "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.
2013-02-08 17:18:43 +01:00
Alexander Barton
0ad0fe207a Implement new function Client_SearchServer()
This function returns the server structure of a client or a given "mask";
it is useful for implemention handlers for commands like "COMMAND *.net",
which should work on a server matching "*.net".

Please note that the local server is always returned when it matches the
mask, but besides that, the order is completely arbitrary.
2013-02-05 13:06:08 +01:00
Alexander Barton
f295117fba New configuration option "IdleTimeout": exit daemon when idle
This patch implements 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.
2013-02-04 23:15:53 +01:00
Alexander Barton
8ab097afb7 Implement support for systemd(8) "socket activation"
This patch enables ngIRCd to work with listening sockets already
initialized and passed-in by systemd(8) and hereby to support on-demand
"socket activation".

systemd(8) uses two environment variables to pass information about the
sockets to ngIRCd, LISTEN_PID and LISTEN_FDS, and this mechanism only
kicks in when both variables are set. In all other cases, and therefore
in most installations out there, nothing changes at all.

Please note:
If socket activation is in effect, ngIRCd will not initialize any (other)
soeckets on its own! All sockets must be configured in the systemd(8)
socket unit configuration file in this case, see ./contrib/ngircd.socket
for example.

Probably it would be interesting to match passed-in sockets to configured
listening sockets and to initialize all the remaining ones not already
set up by systemd(8), but this is kept back for an other patch ...

See
 - <http://0pointer.de/blog/projects/socket-activation.html>
 - <http://0pointer.de/blog/projects/socket-activation2.html>
 - <http://www.freedesktop.org/software/systemd/man/systemd.socket.html>
2013-02-04 21:52:27 +01:00
Alexander Barton
84e24afd2f contrib/README: add more files 2013-02-04 21:31:42 +01:00
Alexander Barton
f16d230530 Rename ports_initlisteners() to Init_Listeners() 2013-02-03 21:43:29 +01:00
Alexander Barton
3a3b3225d4 NewListener(): Code cleanup 2013-02-03 21:43:29 +01:00
Alexander Barton
84a599ece4 Enable WHOIS to display information about IRC Services
This patch introduces the new numeric 310(RPL_WHOISSERVICE) and enables
WHOIS to display information about IRC services. 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 id displayed in the output.

Change suggested by Federico G. Schwindt <fgsch@lodoss.net>, Thanks.
2013-02-03 21:32:53 +01:00
Alexander Barton
b7690a0add Commands.txt: Add description for the "CHARCONV" command 2013-02-03 19:02:42 +01:00
Alexander Barton
18ecc2fd81 Commands.txt: Add description for the "CAP" command 2013-02-03 18:59:44 +01:00
Alexander Barton
999c11ad49 Exit message: use singular & plural :-) 2013-01-27 23:22:00 +01:00
Alexander Barton
c891b5f250 autogen.sh: Check for autoconf/automake wrapper scripts
For example OpenBSD uses a "autoconf" and "automake" wrapper script which
tells the user to set AUTOCONF_VERSION and AUTOMAKE_VERSION environment
variables. This patch enhances autogen.sh to not detect these wrapper
scripts as regular autoconf/automake commands but to set the required
environment variables after detecting the real "command-X.Y" commands.

Tested on OpenBSD 5.1.
2013-01-27 12:54:48 +01:00
Alexander Barton
419ff38a07 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 ...
2013-01-27 12:25:58 +01:00
Alexander Barton
8d8201502f IRC_WHO_Channel(): Use strlcpy() instead of strcpy()
This fixes the following warning, at least on OpenBSD 4.8:

 irc-info.o(.text+0x2427): In function `IRC_WHO':
 src/ngircd/irc-info.c:896: warning: strcpy() is almost always misused,
                            please use strlcpy()
2013-01-27 01:00:32 +01:00
Alexander Barton
d38d153f51 Streamline punctuation of log messages
Make sure that all log messages end with a correct punctuation mark.

The rules for formatting log messages are:

 1. Add punctuation marks to all messages passed to the actual logging
    functions like Log() and LogDebug().
 2. Don't add any punctuation marks to messages that are stored in
    variables for later use or are passed over the network.
 3. IP addresses, DNS host names and IRC server names should be quoted.
 4. Messages originating in the network should be quoted (at least if
    they are "untrusted" or variable).

Most probably this patch doesn't fix all mistakes, but it should be a
good starting point ...
2013-01-26 17:00:03 +01:00
Alexander Barton
fd260404ca 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 :-)
2013-01-24 22:45:00 +01:00
DNS
a551942635 contrib/Debian/rules: Do no compress Commands.txt
This is required, because ngIRCd can't use a compressed file as
help text ...

(cherry picked from commit 6d09b4f366f656f6d2732ea96a653e086380e458)
2013-01-23 19:55:56 +01:00
Alexander Barton
b60d5a0a11 AUTHORS: Update list of contributors 2013-01-23 19:45:00 +01:00
Alexander Barton
fae0054d31 AUTHORS: Use "email address syntax" 2013-01-23 19:41:52 +01:00
Alexander Barton
73fded7515 Commands.txt: Import descriptions from "rbose/command_help"
Import command description texts from the "rbose/command_help" branch,
which have been written by DNS <dns@rbose.org> -- thanks a lot!
2013-01-23 15:16:33 +01:00
Alexander Barton
7630e8ffc6 Commands.txt: Reorder some commands
Reorder some commands and introduce new section "Connection Handling".
Idea by DNS <dns@rbose.org>, thanks!
2013-01-23 15:02:46 +01:00
Alexander Barton
4552ad5269 Commands.txt: Fix some wording and spelling 2013-01-23 14:51:19 +01:00
Alexander Barton
3d49e8ac84 ngircd.service: Use "forking" service type
Don't run ngIRCd in forground mode but let it daemonize itself. This
enhances the log output of "systemctl status ngircd.service", because
now ngIRCd doesn't print out its PID and timestamp on each log message
which is redundant: it becomes logged by systemd/journald already.
2013-01-23 00:44:16 +01:00
Alexander Barton
508ca3044d 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).
2013-01-22 10:54:06 +01:00
Alexander Barton
d8f2964710 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>
2013-01-13 17:18:04 +01:00
Alexander Barton
ab00997698 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>
2013-01-07 20:34:55 +01:00
Alexander Barton
b4966aa1bd configure: use AS_HELP_STRING for --with-iconv 2013-01-06 17:46:06 +01:00
Alexander Barton
0703fcd719 autogen.sh: Enforce serial test harness on automake >=1.13 2013-01-05 03:05:56 +01:00
Alexander Barton
4594583f52 autogen.sh: Reformat messages. 2013-01-05 02:39:06 +01:00
Alexander Barton
68cb1a8c2e Merge branch 'bug145-ProvideHelp'
* bug145-ProvideHelp:
  Use "${docdir}/Commands.txt" as help text file
  Add a note that "help file" is updated on startup and REHASH only
  Add doc/Commands.txt which should document all commands
  Implement Help() function parsing and returning the help text
  Document "HelpFile" in sample-ngircd.conf and ngircd.conf.5
  Implement new configuration option "HelpFile"
  IRC_HELP(): Code cleanup
  Refactor Read_Motd() into Read_TextFile()
2013-01-02 23:41:46 +01:00
Alexander Barton
950aeec3ff Use "${docdir}/Commands.txt" as help text file 2013-01-01 19:25:06 +01:00
Alexander Barton
60a9a7f118 Add a note that "help file" is updated on startup and REHASH only 2013-01-01 15:35:58 +01:00
Alexander Barton
8ec09e3ca4 Add doc/Commands.txt which should document all commands
This document can be used as "help text", too, see configuration option
"HelpFile" in ngircd.conf(5).

Please note that this file in its current state is far from complete, only
a few commands are documented, but you should get an idea how it works.

So please send in patches adding the remaining parts! :-)
2013-01-01 15:11:31 +01:00
Alexander Barton
289a26e9e4 Implement Help() function parsing and returning the help text
This function parses the already read in help text and sends the requested
portions to the user. Parsing is done as following when a user 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.

A special "Intro" block is returned to the user when the HELP command is
used without a command name.
2013-01-01 14:57:03 +01:00
Alexander Barton
d2a1f6aa4b Document "HelpFile" in sample-ngircd.conf and ngircd.conf.5 2012-12-31 21:03:23 +01:00
Alexander Barton
f68aa02272 Implement new configuration option "HelpFile"
This new configuration option allows to specify a specially formatted
text file which can be used by the HELP command to provide information
about the commands and their syntaxes.
2012-12-31 19:29:52 +01:00
Alexander Barton
588af510a3 IRC_HELP(): Code cleanup 2012-12-31 19:27:32 +01:00
Alexander Barton
9e1c25a889 Refactor Read_Motd() into Read_TextFile()
Now this function allows to read arbitrary text files into arrays.
2012-12-31 19:26:31 +01:00
98 changed files with 5905 additions and 3359 deletions

1
.gitignore vendored
View File

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

8
.travis.yml Normal file
View File

@@ -0,0 +1,8 @@
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

46
AUTHORS
View File

@@ -2,7 +2,7 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
(c)2001-2014 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
@@ -18,29 +18,41 @@ Don't mail the people listed here directly, if possible!
Main Authors
~~~~~~~~~~~~
Alexander Barton, <alex@barton.de> (alex)
Florian Westphal, <fw@strlen.de>
Alexander Barton <alex@barton.de>
Florian Westphal <fw@strlen.de>
Contributors
~~~~~~~~~~~~
Ali Shemiran, <ashemira@ucsd.edu>
Ask Bjørn Hansen, <ask@develooper.com>
Benjamin Pineau, <ben@zouh.org>
Brandon Beresini, <beresini@google.com>
Bryan Caldwell, <bcaldwel@ucsd.edu>
Dana Dahlstrom, <dana+ngIRCd@cs.ucsd.edu>
Eric Grunow, <egrunow@ucsd.edu>
Goetz Hoffart, <goetz@hoffart.de>
Ilja Osthoff, <i.osthoff@gmx.net>
Jari Aalto, <jari.aalto@cante.net>
Rolf Eike Beer, <eike@sf-mail.de>
Scott Perry, <scperry@ucsd.edu>
Sean Reifschneider, <jafo-rpms@tummy.com>
Ali Shemiran <ashemira@ucsd.edu>
Ask Bjørn Hansen <ask@develooper.com>
Benjamin Pineau <ben@zouh.org>
Brandon Beresini <beresini@google.com>
Brett Smith <brett@w3.org>
Brian Collins <bricollins@gmail.com>
Bryan Caldwell <bcaldwel@ucsd.edu>
Christoph Biedl <ngircd.anoy@manchmal.in-ulm.de>
DNS <dns@rbose.org>
Dana Dahlstrom <dana+ngIRCd@cs.ucsd.edu>
David Kingston <deathking1337@aim.com>
Eric Grunow <egrunow@ucsd.edu>
Federico G. Schwindt <fgsch@lodoss.net>
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
~~~~~~~~~~~~~
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

242
ChangeLog
View File

@@ -2,13 +2,251 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
(c)2001-2014 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- ChangeLog --
ngIRCd 21.1 (2014-03-25)
- Don't ignore but use the server password when PAM is compiled in but
disabled. Thanks to Roy Sindre Norangshol <roy.sindre@norangshol.no>!
- doc/Platforms.txt: Update from master branch.
- Really kill connections that send "spoofed prefixes" on non-server links.
This fixes commit 6cbe1308 which only killed the connection when the
spoofed prefix itself belonged to a non-server client.
- CHARCONV command: Fix handling conversion errors, don't overwrite already
converted text!
- doc/Services.txt: Update information for Anope 2.x.
- Correctly use cloaked IRC masks on "INVITE nickname": The cloaked IRC mask
of a user is his visible mask, so the daemon has to use it for generating
the "one time" entries for the invite list of the given channel, and not
the "real" mask which will never match while the target client is "+x", and
even worse, will disclose the real mask on "MODE #channel +I" commands :-/
Bug reported by Cahata on #ngircd, thanks!
- configure: Only link "contrib/Debian" if it exists. This isn't the case on
"VPATH builds", for example.
- Use $(MKDIR_P) instead of $(mkinstalldirs) in Makefile's and test for
"mkdir -p" using AC_PROG_MKDIR_P in "configure".
- Fix configure script and "make check" for TCP Wrappers (problems spotted on
OpenBSD): add missing #include's and static variables, and add libwrap at
the end of the configure run because if libwrap becomes added earlier,
other tests may fail.
- configure: add support for the LDFLAGS_END and LIBS_END variables to add
linker flags and libraries at the end of the configure run (CFLAGS_END has
been implemented already).
- platformtest.sh and Makefile.am: Don't use "test -e", it isn't portable.
- Update Copyright notices for 2014 :-)
- Fix permanent {G|K}LINES (with a timeout of 0 seconds).
- WEBIRC: Don't set the hostname received by the WEBIRC command when DNS
lookups are disabled, but use the IP address instead.
Reported by Toni Spets <toni.spets@iki.fi>, thanks!
- Check for working getaddrinfo() function: At least AIX 4.3.3 and 5.1 have a
broken implementation of getaddrinfo() which doesn't handle "0" as numeric
service correctly. This patch adds a configure check for this case and
changes all calling functions to only use getaddrinfo() if it "works".
See <http://www.stacken.kth.se/lists/heimdal-discuss/2004-05/msg00059.html>
- Only use the unsetenv() function when it is available (AIX 4.3 doesn't
support it, for example).
- Make sure that the source code is still compatible with the "ansi2knr" tool
and builds using non-ANSI K&R C compilers. Tested with Apple C on A/UX.
- Fix building ngIRCd without support for ZLIB compression. Reported by
"der_baer" on #ngircd, thanks!
ngIRCd 21 (2013-10-30)
- ./contrib/Debian/ngircd.init: Make sure no stale PID file is left over
when (re-)starting ngIRCd.
- Change ./contrib/platformtest.sh and update ./doc/Platforms.txt to
allow user names up to 8 characters.
- Call arc4random_stir() in forked subprocesses, when available. This
is required by FreeBSD <10 and current NetBSD at least to correctly
initialize the "arc4" random number generator on these platforms.
- Update our own Debian package configuration and fix the default path
of the "HelpFile" of the "full" package variants.
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)
- 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
(CVE-2013-1747).
- 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
the cloaked users on a specific real hostname!
- configure: 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 :-)
- 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.
- 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 ...
- Correctly detect when SSL subsystem must be initialized and take
outgoing connections (server links!) into account, too.
- autogen.sh: Enforce serial test harness on GNU automake >=1.13. The
new parallel test harness which is enabled by default starting with
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 not available on OpenBSD, for example.
ngIRCd 20.1 (2013-01-02)
- Allow ERROR command on server and service links only, ignore them and
@@ -27,7 +265,7 @@ ngIRCd 20 (2012-12-17)
- 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
external (PAM) authenticaion mechanisms that require longer user names.
external (PAM) authentication mechanisms that require longer user names.
Patch suggested by Brett Smith <brett@w3.org>, see
<http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>.

15
INSTALL
View File

@@ -2,7 +2,7 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
(c)2001-2014 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
@@ -12,11 +12,22 @@
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
- Starting with ngIRCd 20, users can "cloak" their hostname only when the
configuration variable "CloakHostModeX" (introduced in 19.2) is set.
Otherwise, only IRC opertators, other servers, and services are allowed to
Otherwise, only IRC operators, other servers, and services are allowed 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 ;-)

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# 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
@@ -15,9 +15,8 @@ SUBDIRS = doc src man contrib
EXTRA_DIST = autogen.sh configure.ng .mailmap
clean-local:
clean-local: osxpkg-clean
rm -f build-stamp*
rm -rf ngircd.dest
maintainer-clean-local:
rm -rf autom4te.cache
@@ -62,14 +61,18 @@ deb:
dpkg-buildpackage -rfakeroot -i
osxpkg: have-packagemaker osxpkg-dest
cd contrib/MacOSX && packagemaker \
cd contrib/MacOSX && packagemaker --no-recommend \
--doc ngIRCd.pmdoc \
--out ../../$(distdir).mpkg
rm -f $(distdir).mpkg.zip
zip -ro9 $(distdir).mpkg.zip $(distdir).mpkg
make osxpkg-clean
osxpkg-clean:
[ ! -r ngircd.dest ] || sudo -n rm -rf ngircd.dest
rm -rf ngircd.dest $(distdir).mpkg
osxpkg-dest: have-xcodebuild clean
osxpkg-dest: have-xcodebuild osxpkg-clean clean
./configure --prefix=/opt/ngircd
make xcode
make -C contrib/MacOSX de.barton.ngircd.plist
@@ -82,8 +85,9 @@ osxpkg-dest: have-xcodebuild clean
rm ngircd.dest/opt/ngircd/etc/ngircd.conf
echo "Have a nice day IRCing!" >ngircd.dest/opt/ngircd/etc/ngircd.motd
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-dest rpm \
srcdoc testsuite xcode xcode-clean
.PHONY: deb have-packagemaker have-xcodebuild lint osxpkg osxpkg-clean \
osxpkg-dest rpm srcdoc testsuite xcode xcode-clean
# -eof-

114
NEWS
View File

@@ -2,13 +2,123 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
(c)2001-2014 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- NEWS --
ngIRCd 21.1 (2014-03-25)
- Don't ignore but use the server password when PAM is compiled in but
disabled. Thanks to Roy Sindre Norangshol <roy.sindre@norangshol.no>!
- doc/Platforms.txt: Update from master branch.
- doc/Services.txt: Update information for Anope 2.x.
- configure: add support for the LDFLAGS_END and LIBS_END variables to add
linker flags and libraries at the end of the configure run (CFLAGS_END has
been implemented already).
- Update Copyright notices for 2014 :-)
ngIRCd 21 (2013-10-30)
- Call arc4random_stir() in forked subprocesses, when available. This
is required by FreeBSD <10 and current NetBSD at least to correctly
initialize the "arc4" random number generator on these platforms.
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)
- This release is a bugfix release only, without new features.
- 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
(CVE-2013-1747).
ngIRCd 20.1 (2013-01-02)
- This release is a bugfix release only, without new features.
@@ -17,7 +127,7 @@ ngIRCd 20 (2012-12-17)
- 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
external (PAM) authenticaion mechanisms that require longer user names.
external (PAM) authentication mechanisms that require longer user names.
Patch suggested by Brett Smith <brett@w3.org>, see
<http://arthur.barton.de/pipermail/ngircd-ml/2012-October/000579.html>.

2
README
View File

@@ -2,7 +2,7 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
(c)2001-2014 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.

View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# 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
@@ -73,8 +73,12 @@ Search()
for name in $searchlist; do
$EXIST "${name}" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "${name}"
return 0
"${name}" --version 2>&1 \
| grep -v "environment variable" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "${name}"
return 0
fi
fi
done
@@ -144,6 +148,15 @@ echo "Searching for required tools ..."
[ -z "$AUTOCONF" ] && AUTOCONF=`Search autoconf 2`
[ "$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=""
[ -z "$GO" -a -n "$CONFIGURE_ARGS" ] && GO=1
@@ -153,37 +166,49 @@ echo "Searching for required tools ..."
[ -z "$AUTOMAKE" ] && Notfound automake
[ -z "$AUTOCONF" ] && Notfound autoconf
AM_VERSION=`$AUTOMAKE --version|head -n 1|egrep -o "([1-9]\.[0-9]+(\.[0-9]+)*)"`
AM_VERSION=`$AUTOMAKE --version | head -n 1 | sed -e 's/.* //g'`
ifs=$IFS; IFS="."; set $AM_VERSION; IFS=$ifs
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"
# De-ANSI-fication?
if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -lt "12" ]; then
# automake < 1.12 => automatic de-ANSI-fication support available
echo "Enabling de-ANSI-fication support (automake $AM_VERSION) ..."
echo " - Enabling de-ANSI-fication support."
sed -e "s|^__ng_PROTOTYPES__|AM_C_PROTOTYPES|g" configure.ng >configure.ac
DEANSI_START=""
DEANSI_END=""
else
# automake >= 1.12 => no de-ANSI-fication support available
echo "Disabling de-ANSI-fication support (automake $AM_VERSION) ..."
echo " - Disabling de-ANSI-fication support."
sed -e "s|^__ng_PROTOTYPES__|AC_C_PROTOTYPES|g" configure.ng >configure.ac
DEANSI_START="#"
DEANSI_END=" # disabled by ./autogen.sh script"
DEANSI_END=" (disabled by ./autogen.sh script)"
fi
sed -e "s|^__ng_Makefile_am_template__|${DEANSI_START}AUTOMAKE_OPTIONS = ansi2knr${DEANSI_END}|g" \
# Serial test harness?
if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -ge "13" ]; then
# automake >= 1.13 => enforce "serial test harness"
echo " - Enforcing serial test harness."
SERIAL_TESTS="serial-tests"
else
# automake < 1.13 => no new test harness, nothing to do
SERIAL_TEST=""
fi
sed -e "s|^__ng_Makefile_am_template__|AUTOMAKE_OPTIONS = ${SERIAL_TESTS} ${DEANSI_START}ansi2knr${DEANSI_END}|g" \
src/portab/Makefile.ng >src/portab/Makefile.am
for makefile_ng in $AM_MAKEFILES; do
makefile_am=`echo "$makefile_ng" | sed -e "s|\.ng\$|\.am|g"`
sed -e "s|^__ng_Makefile_am_template__|${DEANSI_START}AUTOMAKE_OPTIONS = ../portab/ansi2knr${DEANSI_END}|g" \
sed -e "s|^__ng_Makefile_am_template__|AUTOMAKE_OPTIONS = ${SERIAL_TESTS} ${DEANSI_START}../portab/ansi2knr${DEANSI_END}|g" \
$makefile_ng >$makefile_am
done
export ACLOCAL AUTOHEADER AUTOMAKE AUTOCONF
# Generate files
echo "Generating files using GNU $AUTOCONF and $AUTOMAKE ..."
echo "Generating files using \"$AUTOCONF\" and \"$AUTOMAKE\" ..."
Run $ACLOCAL && \
Run $AUTOCONF && \
Run $AUTOHEADER && \

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# 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
@@ -67,6 +67,7 @@ AC_PROG_AWK
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_MKDIR_P
AC_PROG_RANLIB
# -- Compiler Features --
@@ -92,6 +93,35 @@ AC_DEFUN([GCC_STACK_PROTECT_CC],[
fi
])
AC_DEFUN([WORKING_GETADDRINFO],[
AC_CHECK_FUNCS([getaddrinfo],[
AC_MSG_CHECKING([whether getaddrinfo() works])
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int
main(int argc, char **argv)
{
struct addrinfo hints, *ai;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if(getaddrinfo(NULL, "0", &hints, &ai) != 0)
return 1;
return 0;
}
],[
AC_DEFINE([HAVE_WORKING_GETADDRINFO], 1, [getaddrinfo(0)])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
])
])
])
if test "$GCC" = "yes"; then
# We are using the GNU C compiler. Good!
CFLAGS="$CFLAGS -pipe -W -Wall -Wpointer-arith -Wstrict-prototypes"
@@ -110,7 +140,7 @@ esac
# Add additional CFLAGS, eventually specified on the command line:
test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD"
CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'"
CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"' -DDOCDIR='\"\$(docdir)\"'"
# -- Headers --
@@ -120,14 +150,14 @@ AC_HEADER_TIME
# Required header files
AC_CHECK_HEADERS([ \
fcntl.h netdb.h netinet/in.h netinet/in_systm.h stdlib.h string.h \
fcntl.h netdb.h netinet/in.h stdlib.h string.h \
strings.h sys/socket.h sys/time.h unistd.h \
],,AC_MSG_ERROR([required C header missing!]))
# Optional header files
AC_CHECK_HEADERS_ONCE([ \
arpa/inet.h inttypes.h malloc.h netinet/ip.h stdbool.h stddef.h \
stdint.h varargs.h \
arpa/inet.h inttypes.h malloc.h netinet/in_systm.h netinet/ip.h \
stdbool.h stddef.h stdint.h varargs.h \
])
# -- Datatypes --
@@ -186,9 +216,12 @@ AC_CHECK_FUNCS([ \
AC_MSG_ERROR([required function missing!]))
# Optional functions
AC_CHECK_FUNCS_ONCE([ \
gai_strerror getaddrinfo getnameinfo inet_aton sigaction sigprocmask \
snprintf vsnprintf strdup strlcpy strlcat strtok_r waitpid])
AC_CHECK_FUNCS_ONCE([
arc4random arc4random_stir gai_strerror getnameinfo inet_aton \
sigaction sigprocmask snprintf vsnprintf strdup strndup strlcpy strlcat \
strtok_r unsetenv waitpid])
WORKING_GETADDRINFO
# -- Configuration options --
@@ -431,8 +464,12 @@ AC_ARG_WITH(tcp-wrappers,
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_MSG_CHECKING(for hosts_access)
saved_LIBS="$LIBS"
LIBS="-lwrap $LIBS"
LIBS_END="-lwrap $LIBS_END"
AC_TRY_LINK([
#include <sys/types.h>
#include <sys/socket.h>
#include <tcpd.h>
int allow_severity = 0;
int deny_severity = 0;
@@ -446,6 +483,7 @@ int deny_severity = 0;
AC_MSG_RESULT(no)
AC_MSG_ERROR([Can't enable TCP wrappers!])
])
LIBS="$saved_LIBS"
fi
]
)
@@ -518,7 +556,8 @@ if test "$x_ircplus_on" = "yes"; then
# CHARCONV is the only function depending on it.
x_iconv_on=no
AC_ARG_WITH(iconv,
[ --with-iconv enable character conversation using libiconv],
AS_HELP_STRING([--with-iconv],
[enable character conversion using libiconv]),
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
@@ -526,11 +565,15 @@ if test "$x_ircplus_on" = "yes"; then
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
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!])
)
fi
]
fi
fi ]
)
if test "$x_iconv_on" = "yes"; then
AC_DEFINE(ICONV, 1)
@@ -596,9 +639,12 @@ AC_DEFINE_UNQUOTED(HOST_CPU, "$host_cpu" )
AC_DEFINE_UNQUOTED(HOST_VENDOR, "$host_vendor" )
AC_DEFINE_UNQUOTED(HOST_OS, "$host_os" )
# Add additional CFLAGS, eventually specified on the command line, but after
# running this configure script. Useful for "-Werror" for example.
# Add additional CFLAGS, LDFLAGS and LIBS which were specified on the command
# line or by some tests from above, but after running this script. Useful for
# adding "-Werror", for example:
test -n "$CFLAGS_END" && CFLAGS="$CFLAGS $CFLAGS_END"
test -n "$LDFLAGS_END" && LDFLAGS="$LDFLAGS $LDFLAGS_END"
test -n "$LIBS_END" && LIBS="$LIBS $LIBS_END"
# -- Generate files --
@@ -627,7 +673,9 @@ if test $? -eq 0; then
# Generate debian/ link if the dpkg command exists
# (read: if we are running on a debian compatible system)
echo "creating Debian-specific links ..."
test -f debian/rules || ln -s contrib/Debian debian
if test ! -f debian/rules -a -f contrib/Debian/rules; then
ln -s contrib/Debian debian
fi
fi
# -- Result --
@@ -697,7 +745,7 @@ test "$x_ipv6_on" = "yes" \
&& echo $ECHO_N "yes $ECHO_C" \
|| echo $ECHO_N "no $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"
test "$x_pam_on" = "yes" \
@@ -711,7 +759,8 @@ echo $ECHO_N " libiconv support: $ECHO_C"
echo
if ! grep "^AUTOMAKE_OPTIONS = ../portab/ansi2knr" src/ngircd/Makefile.am >/dev/null 2>&1; then
define(_automake_regex_,[[^AUTOMAKE_OPTIONS = [a-z .\-]*/portab/ansi2knr]])
if ! grep "_automake_regex_" src/ngircd/Makefile.am >/dev/null 2>&1; then
echo "WARNING:"
echo "This GNU automake generated build system does not support \"de-ANSI-fication\","
echo "therefore don't use it to generate \"official\" distribution archives!"

View File

@@ -1,3 +1,60 @@
ngircd (21.1-0ab2) unstable; urgency=low
* Use correct package name in pathname to "HelpFile" (Command.txt)
in "ngircd-full" and "ngircd-full-dbg" packages.
* Don't adjust path names that are correct by default.
-- Alexander Barton <alex@barton.de> Mon, 14 Jul 2014 11:20:17 +0200
ngircd (21.1-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 21.1.
-- Alexander Barton <alex@barton.de> Tue, 25 Mar 2014 14:44:59 +0100
ngircd (21-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 21.
-- Alexander Barton <alex@barton.de> Wed, 30 Oct 2013 22:13:55 +0100
ngircd (21~rc2-0ab3) unstable; urgency=low
* Fix sed(1) rules adjusting "ngircd-full" package, error introduced
by last commit :-/
-- Alexander Barton <alex@barton.de> Sun, 20 Oct 2013 18:31:16 +0200
ngircd (21~rc2-0ab2) unstable; urgency=low
* Fix default "HelpFile" file name in ngircd.conf for "full" packages.
-- Alexander Barton <alex@barton.de> Sun, 20 Oct 2013 17:18:28 +0200
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
* New "upstream" release, fixing a security related bug: ngIRCd 20.2.
-- Alexander Barton <alex@barton.de> Fri, 15 Feb 2013 12:17:00 +0100
ngircd (20.1-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 20.1.

View File

@@ -1,8 +1,6 @@
#
# 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
# possible options (default: empty).

View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# ngIRCd start and stop script for Debian-based systems
# Copyright 2008-2010 Alexander Barton <alex@barton.de>
# Copyright 2008-2013 Alexander Barton <alex@barton.de>
#
### BEGIN INIT INFO
@@ -24,13 +24,13 @@ PARAMS=""
STARTTIME=1
DIETIME=10
test -x $DAEMON || exit 5
test -h "$0" && me=`readlink $0` || me="$0"
BASENAME=`basename $me`
test -r /etc/default/$BASENAME && . /etc/default/$BASENAME
test -x $DAEMON || exit 5
# LSB compatibility functions that become used if there is no local
# include file available.
log_daemon_msg() {
@@ -84,6 +84,7 @@ Do_Start() {
log_warning_msg "$NAME seems to be already running, nothing to do."
exit 0
fi
rm -f "$PIDFILE"
start-stop-daemon --start \
--quiet --exec $DAEMON -- $PARAMS
sleep $STARTTIME

View File

@@ -1,7 +1,7 @@
#!/usr/bin/make -f
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# Copyright (c)2001-2014 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
@@ -42,6 +42,7 @@ configure-ngircd: configure
--prefix=/usr \
--sysconfdir=/etc/ngircd \
--mandir=\$${prefix}/share/man \
--docdir=\$${prefix}/share/doc/ngircd \
--with-syslog --with-zlib
configure-ngircd-full: configure
@@ -52,6 +53,7 @@ configure-ngircd-full: configure
--prefix=/usr \
--sysconfdir=/etc/ngircd \
--mandir=\$${prefix}/share/man \
--docdir=\$${prefix}/share/doc/ngircd-full \
--with-syslog --with-zlib \
--with-gnutls --with-iconv --with-ident --with-tcp-wrappers \
--with-pam \
@@ -65,6 +67,7 @@ configure-ngircd-full-dbg: configure
--prefix=/usr \
--sysconfdir=/etc/ngircd \
--mandir=\$${prefix}/share/man \
--docdir=\$${prefix}/share/doc/ngircd-full-dbg \
--enable-debug --enable-sniffer \
--with-syslog --with-zlib \
--with-gnutls --with-iconv --with-ident --with-tcp-wrappers \
@@ -139,10 +142,9 @@ install-ngircd: build-ngircd
rm $(CURDIR)/debian/ngircd/usr/share/doc/ngircd/COPYING*
mkdir -p $(CURDIR)/debian/ngircd/var/run/ircd
cat $(CURDIR)/debian/ngircd/usr/share/doc/ngircd/sample-ngircd.conf | \
sed -e "s/;ServerUID = 65534/ServerUID = irc/g" | \
sed -e "s/;ServerGID = 65534/ServerGID = irc/g" | \
sed -e "s/;MotdFile = \/usr\/local\/etc\/ngircd.motd/MotdFile = \/etc\/ngircd\/ngircd.motd/g" | \
sed -e "s/;PidFile = \/var\/run\/ngircd\/ngircd.pid/PidFile = \/var\/run\/ircd\/ngircd.pid/g" \
sed -e "s|;ServerUID = 65534|ServerUID = irc|g" | \
sed -e "s|;ServerGID = 65534|ServerGID = irc|g" | \
sed -e "s|;PidFile = /var/run/ngircd/ngircd.pid|PidFile = /var/run/ircd/ngircd.pid|g" \
>$(CURDIR)/debian/ngircd/etc/ngircd/ngircd.conf
touch $(CURDIR)/debian/ngircd/etc/ngircd/ngircd.motd
@@ -153,16 +155,13 @@ install-ngircd-full: build-ngircd-full
# Add here commands to install the "full" package into debian/ngircd-full:
$(MAKE) install DESTDIR=$(CURDIR)/debian/ngircd-full
rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd/INSTALL*
rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd/COPYING*
mv $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd \
$(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full
rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full/INSTALL*
rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full/COPYING*
mkdir -p $(CURDIR)/debian/ngircd-full/var/run/ircd
cat $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full/sample-ngircd.conf | \
sed -e "s/;ServerUID = 65534/ServerUID = irc/g" | \
sed -e "s/;ServerGID = 65534/ServerGID = irc/g" | \
sed -e "s/;MotdFile = \/usr\/local\/etc\/ngircd.motd/MotdFile = \/etc\/ngircd\/ngircd.motd/g" | \
sed -e "s/;PidFile = \/var\/run\/ngircd\/ngircd.pid/PidFile = \/var\/run\/ircd\/ngircd.pid/g" \
sed -e "s|;ServerUID = 65534|ServerUID = irc|g" | \
sed -e "s|;ServerGID = 65534|ServerGID = irc|g" | \
sed -e "s|;PidFile = /var/run/ngircd/ngircd.pid|PidFile = /var/run/ircd/ngircd.pid|g" \
>$(CURDIR)/debian/ngircd-full/etc/ngircd/ngircd.conf
touch $(CURDIR)/debian/ngircd-full/etc/ngircd/ngircd.motd
mkdir -p $(CURDIR)/debian/ngircd-full/etc/pam.d
@@ -175,16 +174,13 @@ install-ngircd-full-dbg: build-ngircd-full-dbg
# Add here commands to install the "full" package into debian/ngircd-full:
$(MAKE) install DESTDIR=$(CURDIR)/debian/ngircd-full-dbg
rm $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd/INSTALL*
rm $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd/COPYING*
mv $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd \
$(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd-full-dbg
rm $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd-full-dbg/INSTALL*
rm $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd-full-dbg/COPYING*
mkdir -p $(CURDIR)/debian/ngircd-full-dbg/var/run/ircd
cat $(CURDIR)/debian/ngircd-full-dbg/usr/share/doc/ngircd-full-dbg/sample-ngircd.conf | \
sed -e "s/;ServerUID = 65534/ServerUID = irc/g" | \
sed -e "s/;ServerGID = 65534/ServerGID = irc/g" | \
sed -e "s/;MotdFile = \/usr\/local\/etc\/ngircd.motd/MotdFile = \/etc\/ngircd\/ngircd.motd/g" | \
sed -e "s/;PidFile = \/var\/run\/ngircd\/ngircd.pid/PidFile = \/var\/run\/ircd\/ngircd.pid/g" \
sed -e "s|;ServerUID = 65534|ServerUID = irc|g" | \
sed -e "s|;ServerGID = 65534|ServerGID = irc|g" | \
sed -e "s|;PidFile = /var/run/ngircd/ngircd.pid|PidFile = /var/run/ircd/ngircd.pid|g" \
>$(CURDIR)/debian/ngircd-full-dbg/etc/ngircd/ngircd.conf
touch $(CURDIR)/debian/ngircd-full-dbg/etc/ngircd/ngircd.motd
mkdir -p $(CURDIR)/debian/ngircd-full-dbg/etc/pam.d
@@ -216,7 +212,7 @@ binary-arch: build install
dh_installdocs -a
dh_installinit -a
dh_strip -a --no-package=ngircd-full-dbg
dh_compress -a
dh_compress -a -XCommands.txt
dh_fixperms -a
dh_installdeb -a
dh_shlibdeps -a

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -12,17 +12,22 @@
*/
#define PACKAGE_NAME "ngIRCd"
#define PACKAGE "ngircd"
# define PACKAGE "ngircd"
#ifndef VERSION
#define VERSION "??("__DATE__")"
# define VERSION "??("__DATE__")"
#endif
#define SYSCONFDIR "/etc/ngircd"
#ifndef TARGET_VENDOR
#define TARGET_VENDOR "apple"
#define TARGET_OS "darwin"
#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 DOCDIR "/usr/share/doc/ngircd"
/* -- Build options -- */
/* Define if debug-mode should be enabled */
@@ -100,6 +105,8 @@
#define HAVE_INET_ATON 1
/* Define to 1 if you have the `getaddrinfo' function. */
#define HAVE_GETADDRINFO 1
/* getaddrinfo(0) */
#define HAVE_WORKING_GETADDRINFO 1
/* Define to 1 if you have the `getnameinfo' function. */
#define HAVE_GETNAMEINFO 1
/* Define to 1 if you have the `sigaction' function. */

View File

@@ -1 +1 @@
<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>
<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>

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>/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>
<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>

View File

@@ -1,11 +1,11 @@
<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">/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
<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
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
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
\f0\i\fs24 \cf0 ngIRCd -- The Next Generation IRC Daemon\
Copyright (c)2001-2013 Alexander Barton and Contributors.\
Copyright (c)2001-2014 Alexander Barton and Contributors.\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
\i0 \cf0 \

View File

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

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# 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
@@ -17,6 +17,7 @@ EXTRA_DIST = README \
ngIRCd-Logo.gif \
ngircd-redhat.init \
ngircd.service \
ngircd.socket \
ngircd.spec \
platformtest.sh \
systrace.policy

View File

@@ -2,18 +2,21 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2011 Alexander Barton and Contributors.
(c)2001-2013 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- Contributions --
-- Contributions --
Debian/
- 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/
- Project files for XCode, the "project builder" of Apple Mac OS X.
- de.barton.ngircd.plist[.tmpl]: launchd(8) property list.
ngindent
- Script to indent the code of ngIRCd in the "standard way".
@@ -24,6 +27,12 @@ ngircd-bsd.sh
ngircd-redhat.init
- 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
- RPM "spec" file.

View File

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

11
contrib/ngircd.socket Normal file
View File

@@ -0,0 +1,11 @@
[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 version 20.1
%define version 21.1
%define release 1
%define prefix %{_prefix}

View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors
# Copyright (c)2001-2014 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
@@ -54,8 +54,18 @@ if [ $? -ne 0 ]; then
cd ..
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 ..."
if [ ! -e ./configure ]; then
if [ ! -r ./configure ]; then
echo "$NAME: Running \"./autogen.sh\" ..."
[ -n "$VERBOSE" ] && ./autogen.sh || ./autogen.sh >/dev/null
fi
@@ -99,6 +109,7 @@ if [ -r "Makefile" ]; then
CC=$(grep "^CC = " Makefile | cut -d' ' -f3)
$CC --version 2>&1 | grep -i "GCC" >/dev/null
if [ $? -eq 0 ]; then
# GCC, or compiler that mimics GCC
$CC --version 2>&1 | grep -i "Open64" >/dev/null
if [ $? -eq 0 ]; then
COMPILER="Open64"
@@ -108,12 +119,24 @@ if [ -r "Makefile" ]; then
COMPILER="gcc $COMPILER"
fi
else
case "$CC" in
gcc*)
# Non-GCC compiler
$CC --version 2>&1 | grep -i "clang" >/dev/null
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`"
[ -n "$v" ] && COMPILER="gcc $v"
;;
esac
[ -z "$v" ] && v="`$CC -version 2>/dev/null | head -1`"
[ -n "$v" ] && COMPILER="$v"
fi
fi
fi
@@ -128,14 +151,14 @@ esac
# Get IO interface information
if [ "$OS" = "linux-gnu" ]; then
COMMENT="(1)"
COMMENT="1"
else
grep "^#define HAVE_SYS_DEVPOLL_H 1" src/config.h >/dev/null 2>&1
[ $? -eq 0 ] && COMMENT="(4)"
[ $? -eq 0 ] && COMMENT="4"
grep "^#define HAVE_EPOLL_CREATE 1" src/config.h >/dev/null 2>&1
[ $? -eq 0 ] && COMMENT="(5)"
[ $? -eq 0 ] && COMMENT="5"
grep "^#define HAVE_KQUEUE 1" src/config.h >/dev/null 2>&1
[ $? -eq 0 ] && COMMENT="(3)"
[ $? -eq 0 ] && COMMENT="3"
fi
[ -n "$R_CONFIGURE" ] && C="Y" || C="N"
@@ -145,16 +168,16 @@ fi
[ -n "$COMMENT" ] && COMMENT=" $COMMENT"
echo
echo " the executable works (\"runs\") as expected --+"
echo " tests run successfully (\"make check\") --+ |"
echo " ngIRCd compiles (\"make\") --+ | |"
echo " ./configure works --+ | | |"
echo " | | | |"
echo "Platform Compiler ngIRCd Date Tester C M T R See"
echo "--------------------------- ------------ ---------- -------- ------ - - - - ---"
echo " the executable works (\"runs\") as expected --+"
echo " tests run successfully (\"make check\") --+ |"
echo " ngIRCd compiles (\"make\") --+ | |"
echo " ./configure works --+ | | |"
echo " | | | |"
echo "Platform Compiler ngIRCd Date Tester C M T R *"
echo "--------------------------- ------------ ---------- -------- -------- - - - - -"
type printf >/dev/null 2>&1
if [ $? -eq 0 ]; then
printf "%-27s %-12s %-10s %s %-6s %s %s %s %s%s" \
printf "%-27s %-12s %-10s %s %-8s %s %s %s %s%s" \
"$PLATFORM" "$COMPILER" "$VERSION" "$DATE" "$USER" \
"$C" "$M" "$T" "$R" "$COMMENT"
else

991
doc/Commands.txt Normal file
View File

@@ -0,0 +1,991 @@
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
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# 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
@@ -12,6 +12,7 @@
.tmpl:
$(AM_V_GEN)sed \
-e "s@:ETCDIR:@${sysconfdir}@" \
-e "s@:DOCDIR:@${docdir}@" \
<$< >$@
SUFFIXES = .tmpl
@@ -19,6 +20,7 @@ SUFFIXES = .tmpl
static_docs = \
Bopm.txt \
Capabilities.txt \
Commands.txt \
Contributing.txt \
FAQ.txt \
GIT.txt \
@@ -52,11 +54,11 @@ maintainer-clean-local:
all: $(generated_docs)
install-data-hook: $(static_docs) $(toplevel_docs) $(generated_docs)
$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
$(MKDIR_P) -m 755 $(DESTDIR)$(sysconfdir)
@if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \
make install-config; \
fi
$(mkinstalldirs) $(DESTDIR)$(docdir)
$(MKDIR_P) -m 755 $(DESTDIR)$(docdir)
for f in $(static_docs) $(toplevel_docs); do \
$(INSTALL) -m 644 -c $(srcdir)/$$f $(DESTDIR)$(docdir)/; \
done

View File

@@ -1,9 +1,8 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2010 Alexander Barton,
alex@barton.de, http://www.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
@@ -34,3 +33,13 @@ is running as. Therefore a lot of PAM modules aren't working as expected,
because they need root privileges ("pam_unix", for example)!
Only PAM modules not(!) requiring root privileges (such as "pam_pgsql",
"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,87 +2,106 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2012 Alexander Barton and Contributors.
(c)2001-2013 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- Platforms.txt --
This file lists the status of all platforms on which the ngIRCd has been
tested. Included is the date and version of the last "official" test and
the name of the tester/maintainer.
This file lists the status of all platforms on which ngIRCd has been tested.
Included is the date and version of the last test and the name of the tester
or maintainer.
If you successfully compiled and tested ngIRCd on a platform that isn't
listed here, please contact Alexander Barton, <alex@barton.de>, so that this
list can be updated. Thanks for your help!
If you successfully compiled and tested ngIRCd on a platform that isn't listed
here, please write to the mailing list so that this list can be updated. The
script "./contrib/platformtest.sh" should output a summary that is suitable
for inclusion here. Thanks for your help!
the executable works ("runs") as expected --+
tests run successfully ("make check") --+ |
ngIRCd compiles ("make") --+ | |
./configure works --+ | | |
| | | |
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
hppa2.0w-hp-hpux11.11 gcc 4.2.3 14.1 09-07-22 goetz Y Y Y Y
i386/apple/darwin9.7.0 gcc 4.0.1 14.1 09-08-04 alex Y Y Y Y (3)
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 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 20~rc1 12-11-13 alex Y Y Y Y (3)
i386/unknown/freebsd7.3 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3)
i686/unknown/gnu0.3 gcc 4.4.5 19 12-02-29 alex Y Y Y Y
i686/unkn./kfreebsd7.2-gnu gcc 4.3.4 15 09-12-02 alex Y Y Y Y (3)
i386/unknown/netbsdelf1.6.2 gcc 2.95.3 18 11-07-10 goetz Y Y Y Y
i386/unknown/netbsdelf3.0.1 gcc 3.3.3 0.10.0-p1 06-08-30 alex Y Y Y Y (3)
i386/unknown/netbsdelf4.0 gcc 4.1.2 19 12-02-29 alex Y Y Y Y (3)
i386/unknown/netbsdelf5.0.2 gcc 4.1.3 19 12-02-26 alex Y Y Y Y (3)
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/haiku gcc 2.95.3 19.2~138 12-10-11 user Y Y N N
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)
i686/pc/linux-gnu gcc 4.3.2 14.1 09-08-04 alex Y Y Y Y (1)
m68k/apple/aux3.0.1 gcc 2.7.2 17 10-11-07 alex Y Y N Y
m68k/apple/aux3.0.1 Orig. A/UX 17 10-11-07 alex Y Y N Y (2)
m68k/apple/aux3.1.1 gcc 2.7.2 19 12-02-26 alex Y Y N Y
m68k/apple/aux3.1.1 Orig. A/UX 19 12-02-26 alex Y Y N Y (2)
m68k/hp/hp-ux9.10 Orig. HPUX 0.7.x-CVS 03-04-30 goetz Y Y Y Y
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 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
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/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y
x86_64/apple/darwin12.2.0 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/unknown/linux-gnu gcc 4.4.5 20~rc1 12-02-26 alex 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.8 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3)
the executable works ("runs") as expected --+
tests run successfully ("make check") --+ |
ngIRCd compiles ("make") --+ | |
./configure works --+ | | |
| | | |
Platform Compiler ngIRCd Date Tester C M T R *
--------------------------- ------------ ---------- -------- -------- - - - - -
alpha/unknown/netbsd3.0 gcc 3.3.3 CVSHEAD 06-05-07 fw Y Y Y Y 3
armv6l/unk./linux-gnueabi gcc 4.7.2 20.2 13-03-08 goetz Y Y Y Y 5
armv6l/unk./linux-gnueabihf gcc 4.6.3 21~rc2 13-10-26 pi Y Y Y Y 5
armv7l/unk./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/openbsd5.4 gcc 4.2.1 21 13-11-10 alex Y Y Y Y 3
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
hppa2.0w-hp-hpux11.11 gcc 4.2.3 14.1 09-07-22 goetz Y Y Y Y
i386/apple/darwin9.7.0 gcc 4.0.1 14.1 09-08-04 alex Y Y Y Y 3
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 4.5.2 21~rc2 13-10-27 alex Y Y N 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 20~rc1 12-11-13 alex Y Y Y Y 3
i386/unknown/freebsd7.3 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y 3
i686/pc/minix gcc 4.4.6 21~rc2 13-10-27 alex Y Y N N
i686/unknown/gnu0.3 gcc 4.4.5 19 12-02-29 alex Y Y Y Y
i686/unknown/gnu0.5 gcc 4.8.2 21 14-02-09 alex Y Y Y Y
i686/unkn./kfreebsd7.2-gnu gcc 4.3.4 15 09-12-02 alex Y Y Y Y 3
i386/unknown/netbsdelf1.5.2 egcs-1.1.2 21 13-11-25 goetz Y Y N Y
i386/unknown/netbsdelf1.6.2 gcc 2.95.3 18 11-07-10 goetz Y Y Y Y
i386/unknown/netbsdelf3.0.1 gcc 3.3.3 0.10.0-p1 06-08-30 alex Y Y Y Y 3
i386/unknown/netbsdelf4.0 gcc 4.1.2 19 12-02-29 alex Y Y Y Y 3
i386/unknown/netbsdelf5.0.2 gcc 4.1.3 19 12-02-26 alex Y Y Y Y 3
i386/unknown/openbsd3.5 gcc 2.95.3 21 13-11-17 goetz Y Y Y Y 3
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
i386/unknown/openbsd5.3 gcc 4.2.1 21 13-11-28 goetz Y Y Y Y 3
i386/unknown/openbsd5.4 gcc 4.2.1 21 13-11-28 goetz Y Y Y Y 3
i586/pc/haiku gcc 2.95.3 19.2~138 12-10-11 user Y Y N N
i586/pc/interix3.5 gcc 3.3 19 12-02-29 alex Y Y N Y
i686/pc/cygwin gcc 4.8.2 21 14-01-02 alex Y Y N Y
i686/pc/linux-gnu gcc 2.7.2 21~38 14-01-06 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
i686/pc/linux-gnu gcc 4.3.2 14.1 09-08-04 alex Y Y Y Y 1
m68k/apple/aux3.0.1 gcc 2.7.2 17 10-11-07 alex Y Y N Y
m68k/apple/aux3.0.1 Orig. A/UX 17 10-11-07 alex Y Y N Y 2
m68k/apple/aux3.1.1 gcc 2.7.2 19 12-02-26 alex Y Y N Y
m68k/apple/aux3.1.1 Orig. A/UX 19 12-02-26 alex Y Y N Y 2
m68k/hp/hp-ux9.10 Orig. HPUX 0.7.x-CVS 03-04-30 goetz Y Y Y Y
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 21 13-11-24 goetz Y Y Y Y 1
powerpc/apple/darwin6.8 gcc 3.1 21 14-01-03 goetz Y Y Y Y
powerpc/apple/darwin7.9.0 gcc 3.3 21 14-01-11 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/apple/darwin9.8.0 gcc 4.0.1 21 14-01-04 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
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/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y
x86_64/apple/darwin10.8.0 gcc 4.2.1 21~rc2 13-10-30 alex Y Y Y Y 3
x86_64/apple/darwin12.3.0 gcc 4.2.1 20.2 13-04-01 alex Y Y Y Y 3
x86_64/apple/darwin13.0.0 A-clang 5.0 21 14-01-02 alex Y Y Y Y 3
x86_64/unknown/dragonfly3.4 gcc 4.7.2 21 13-11-12 goetz Y Y N Y 3
x86_64/unknown/freebsd8.4 gcc 4.2.1 21 14-01-02 alex Y Y Y Y 3
x86_64/unknown/freebsd9.1 gcc 4.2.1 21 14-01-02 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.3 21 14-01-07 alex Y Y Y Y 1
x86_64/unknown/linux-gnu gcc 4.8.2 21 13-12-29 alex Y Y Y Y 1
x86_64/unknown/linux-gnu nwcc 0.8.2 21 13-12-01 goetz Y Y Y Y 1
x86_64/unknown/linux-gnu Open64 21 13-11-30 goetz Y Y Y Y 1
x86_64/unknown/linux-gnu Sun C 5.12 21 13-11-22 goetz Y Y Y Y 1
x86_64/unknown/linux-gnu tcc 0.9.25 21 13-11-30 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.8 gcc 4.2.1 21 13-12-28 alex Y Y Y Y 3
x86_64/unknown/openbsd5.1 gcc 4.2.1 21 13-12-28 alex Y Y Y Y 3
Notes
~~~~~
* Notes
~~~~~~~
(1) */*/linux-gnu (Linux platforms):
ngIRCd has been tested with various Linux distributions, such as SuSE,

View File

@@ -224,8 +224,10 @@ new server link", <serverflag> "M"), even if it doesn't support the given
The following <key> names are defined:
- "host": the hostname of a client (can't be empty)
- "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)
- "info": info text ("real name") of a client
- "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.
Support for Services has been tested using
- Anope 1.9.8 or later (<http://www.anope.org/>; unreleased!)
- Anope 1.9.8 or later (<http://www.anope.org/>)
- Atheme 7.0.2 or later (<http://www.atheme.net>)
- "IRC Services" 5.1.x by Andrew Church (<http://achurch.org/services/>)
@@ -41,13 +41,11 @@ Example:
ServiceMask = *Serv
Setting up Anope 1.9.x
~~~~~~~~~~~~~~~~~~~~~~
Setting up Anope 1.9.x & 2.x
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Anope 1.9.8 or later (<http://www.anope.org/>; unreleased as of 2012-11-10)
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/>!
Anope 1.9.8 or later (<http://www.anope.org/>) can be used with ngIRCd using
the "ngircd" protocol module.
At least the following settings have to be tweaked, in addition to all the
settings marked as required by Anope:
@@ -68,20 +66,28 @@ In conf/services.conf:
}
# Load ngIRCd protocol module
module { name = "ngircd" }
module
{
name = "ngircd"
}
networkinfo
{
# Must be set to the "MaxNickLength" setting of ngIRCd!
nicklen = 9
# When not using "strict mode", which is the default:
userlen = 20
chanlen = 50
}
In conf/nickserv.conf:
nickserv
module
{
name = "nickserv"
# not required if you are running ngIRCd with a higher nickname limit
# ("MaxNickLength") than 11 characters, but REQUIRED by default!
guestnickprefix = "G-"

View File

@@ -33,6 +33,10 @@
;AdminInfo2 = Location
;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
# LINKS requests for example.
Info = Server Info Text
@@ -84,6 +88,13 @@
# to not yet (or no longer) connected servers.
;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
# server is allowed to accept (0: unlimited):
;MaxConnections = 0
@@ -117,6 +128,12 @@
# behavior of ngIRCd. If you want to get started quickly, you most
# 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.
# use commands like CONNECT, SQUIT, DIE, ...?
;AllowRemoteOper = no
@@ -148,7 +165,12 @@
;ConnectIPv6 = yes
;ConnectIPv4 = yes
# Do any DNS lookups when a client connects to the server.
# 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.
;DefaultUserModes = i
# Do DNS lookups when a client connects to the server.
;DNS = yes
# Do IDENT lookups if ngIRCd has been compiled with support for it.
@@ -156,6 +178,10 @@
# prepended to their user name.
;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)
# by censoring some information like idle time, logon time, etc.
;MorePrivacy = no
@@ -194,9 +220,6 @@
# character prepended to their respective user names!
;PAMIsOptional = no
# Allow Pre-Defined Channels only (see Section [Channels])
;PredefChannelsOnly = no
# Let ngIRCd send an "authentication PING" when a new client connects,
# and register this client only after receiving the corresponding
# "PONG" reply.
@@ -225,6 +248,15 @@
# SSL Server Key Certificate
;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
;DHFile = :ETCDIR:/ssl/dhparams.pem

View File

@@ -16,106 +16,55 @@
# Project related configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = ngIRCd
# 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.
PROJECT_BRIEF = "Lightweight Internet Relay Chat server"
PROJECT_LOGO = "../../contrib/ngIRCd-Logo.gif"
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 = ../..
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# 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.
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
TYPEDEF_HIDES_STRUCT = YES
TAB_SIZE = 8
#---------------------------------------------------------------------------
# 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
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
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
#---------------------------------------------------------------------------
# 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
#---------------------------------------------------------------------------
# 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
# 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.
INPUT_ENCODING = UTF-8
RECURSIVE = YES
#---------------------------------------------------------------------------
# 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
# 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
# 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
# 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
#---------------------------------------------------------------------------
@@ -123,19 +72,7 @@ REFERENCES_RELATION = 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
# 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
GENERATE_DOCSET = NO
@@ -151,14 +88,6 @@ GENERATE_PERLMOD = NO
# 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__
# -eof-

View File

@@ -1,6 +1,6 @@
<hr class="footer">
<p>
<p style="text-align: center">
ngIRCd
<a href="http://ngircd.barton.de/">Homepage</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
.\"
.TH ngircd 8 "Oct 2012" ngIRCd "ngIRCd Manual"
.TH ngircd 8 "Oct 2013" ngIRCd "ngIRCd Manual"
.SH NAME
ngIRCd \- the "next generation" IRC daemon
.SH SYNOPSIS
@@ -23,13 +23,15 @@ which is a little bit exaggerated:
.IR "lightweight Internet Relay Chat server"
most probably would have been a better name :-)
.PP
Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, IRIX,
Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
.PP
Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, Hurd, IRIX,
Linux, Mac OS X, Minix, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
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
systems as well. By default, ngIRCd writes diagnostic and informational
messages using the syslog mechanism.
systems as well.
.PP
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
The default behavior of
.BR ngircd

View File

@@ -1,7 +1,7 @@
.\"
.\" ngircd.conf(5) manual page template
.\"
.TH ngircd.conf 5 "Nov 2012" ngIRCd "ngIRCd Manual"
.TH ngircd.conf 5 "Oct 2013" ngIRCd "ngIRCd Manual"
.SH NAME
ngircd.conf \- configuration file of ngIRCd
.SH SYNOPSIS
@@ -101,6 +101,12 @@ IRC network and must contain at least one dot (".") character.
Information about the server and the administrator, used by the ADMIN
command. This information is not required by the server but by RFC!
.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)
Info text of the server. This will be shown by WHOIS and LINKS requests for
example.
@@ -127,8 +133,8 @@ if ngIRCd is using PAM!
.TP
\fBPidFile\fR (string)
This tells ngIRCd to write its current process ID to a file. Note that the
pidfile is written AFTER chroot and switching the user ID, e.g. the directory
the pidfile resides in must be writable by the ngIRCd user and exist in the
"PID file" 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
chroot directory (if configured, see above).
.TP
\fBPorts\fR (list of numbers)
@@ -164,6 +170,12 @@ should be safe, but it is wise to double-check :-)
The server tries every <ConnectRetry> seconds to establish a link to not yet
(or no longer) connected servers. Default: 60.
.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)
Maximum number of simultaneous in- and outbound connections the server is
allowed to accept (0: unlimited). Default: 0.
@@ -197,6 +209,12 @@ 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
make changes here -- they are all optional.
.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)
Are IRC operators connected to remote servers allowed to control this server,
e.g. are they allowed to use administrative commands like CONNECT, DIE,
@@ -240,6 +258,12 @@ Set this to no if you do not want ngIRCd to connect to other IRC servers using
the IPv6 protocol.
Default: yes.
.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)
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
@@ -253,6 +277,11 @@ Users identified using IDENT are registered without the "~" character
prepended to their user name.
Default: yes.
.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)
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
@@ -302,12 +331,6 @@ able to distinguish between Ident'ified and PAM-authenticated users: both
don't have a "~" character prepended to their respective user names!
Default: no.
.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)
Let ngIRCd send an "authentication PING" when a new client connects, and
register this client only after receiving the corresponding "PONG" reply.
@@ -343,6 +366,12 @@ when it is compiled with support for SSL using OpenSSL or GnuTLS!
\fBCertFile\fR (string)
SSL Certificate file of the private server key.
.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)
Name of the Diffie-Hellman Parameter file. Can be created with GnuTLS
"certtool \-\-generate-dh-params" or "openssl dhparam". If this file is not

View File

@@ -23,7 +23,7 @@
GLOBAL bool
ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
{
#ifdef HAVE_GETADDRINFO
#ifdef HAVE_WORKING_GETADDRINFO
int ret;
char portstr[64];
struct addrinfo *res0;

View File

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

View File

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

View File

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

View File

@@ -79,7 +79,6 @@ GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
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_Key PARAMS(( CHANNEL *Chan ));
GLOBAL unsigned long Channel_MaxUsers PARAMS(( CHANNEL *Chan ));
@@ -106,9 +105,12 @@ GLOBAL bool Channel_IsValidName PARAMS(( const char *Name ));
GLOBAL bool Channel_ModeAdd 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_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 bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client ));

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2014 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
@@ -33,8 +33,6 @@
struct list_head My_Classes[CLASS_COUNT];
char Reject_Reason[COMMAND_LEN];
GLOBAL void
Class_Init(void)
{
@@ -49,32 +47,31 @@ Class_Exit(void)
for (i = 0; i < CLASS_COUNT; Lists_Free(&My_Classes[i++]));
}
GLOBAL char *
Class_GetMemberReason(const int Class, CLIENT *Client)
GLOBAL bool
Class_GetMemberReason(const int Class, CLIENT *Client, char *reason, size_t len)
{
char *reason;
char str[COMMAND_LEN];
assert(Class < CLASS_COUNT);
assert(Client != NULL);
reason = Lists_CheckReason(&My_Classes[Class], Client);
if (!reason)
return NULL;
strlcpy(str, "listed", sizeof(str));
if (!*reason)
reason = "listed";
if (!Lists_CheckReason(&My_Classes[Class], Client, str, sizeof(str)))
return false;
switch(Class) {
case CLASS_GLINE:
snprintf(Reject_Reason, sizeof(Reject_Reason),
"\"%s\" (G-Line)", reason);
return Reject_Reason;
snprintf(reason, len, "\"%s\" (G-Line)", str);
break;
case CLASS_KLINE:
snprintf(Reject_Reason, sizeof(Reject_Reason),
"\"%s\" (K-Line)", reason);
return Reject_Reason;
snprintf(reason, len, "\"%s\" (K-Line)", str);
break;
default:
snprintf(reason, len, "%s", str);
break;
}
return reason;
return true;
}
/**
@@ -88,15 +85,13 @@ Class_GetMemberReason(const int Class, CLIENT *Client)
GLOBAL bool
Class_HandleServerBans(CLIENT *Client)
{
char *rejectptr;
char reject[COMMAND_LEN];
assert(Client != NULL);
rejectptr = Class_GetMemberReason(CLASS_GLINE, Client);
if (!rejectptr)
rejectptr = Class_GetMemberReason(CLASS_KLINE, Client);
if (rejectptr) {
Client_Reject(Client, rejectptr, true);
if (Class_GetMemberReason(CLASS_GLINE, Client, reject, sizeof(reject)) ||
Class_GetMemberReason(CLASS_KLINE, Client, reject, sizeof(reject))) {
Client_Reject(Client, reject, true);
return DISCONNECTED;
}
@@ -105,24 +100,30 @@ Class_HandleServerBans(CLIENT *Client)
GLOBAL bool
Class_AddMask(const int Class, const char *Mask, time_t ValidUntil,
Class_AddMask(const int Class, const char *Pattern, time_t ValidUntil,
const char *Reason)
{
char mask[MASK_LEN];
assert(Class < CLASS_COUNT);
assert(Mask != NULL);
assert(Pattern != NULL);
assert(Reason != NULL);
return Lists_Add(&My_Classes[Class], Lists_MakeMask(Mask),
Lists_MakeMask(Pattern, mask, sizeof(mask));
return Lists_Add(&My_Classes[Class], mask,
ValidUntil, Reason);
}
GLOBAL void
Class_DeleteMask(const int Class, const char *Mask)
Class_DeleteMask(const int Class, const char *Pattern)
{
assert(Class < CLASS_COUNT);
assert(Mask != NULL);
char mask[MASK_LEN];
Lists_Del(&My_Classes[Class], Lists_MakeMask(Mask));
assert(Class < CLASS_COUNT);
assert(Pattern != NULL);
Lists_MakeMask(Pattern, mask, sizeof(mask));
Lists_Del(&My_Classes[Class], mask);
}
GLOBAL struct list_head *

View File

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

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de)
* 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
@@ -41,6 +41,7 @@
#include "hash.h"
#include "irc-write.h"
#include "log.h"
#include "match.h"
#include "messages.h"
#include <exp.h>
@@ -61,6 +62,8 @@ static CLIENT *New_Client_Struct PARAMS(( void ));
static void Generate_MyToken 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,
CLIENT *TopServer, int Type, const char *ID,
const char *User, const char *Hostname, const char *Info,
@@ -86,7 +89,7 @@ Client_Init( void )
exit( 1 );
}
/* Client-Struktur dieses Servers */
/* Client structure for this server */
This_Server->next = NULL;
This_Server->type = CLIENT_SERVER;
This_Server->conn_id = NONE;
@@ -119,14 +122,15 @@ Client_Exit( void )
cnt = 0;
c = My_Clients;
while( c )
{
while(c) {
cnt++;
next = (CLIENT *)c->next;
free( c );
Free_Client(&c);
c = next;
}
if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
if (cnt)
Log(LOG_INFO, "Freed %d client structure%s.",
cnt, cnt == 1 ? "" : "s");
} /* Client_Exit */
@@ -216,8 +220,8 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
if (Type == CLIENT_SERVER)
Generate_MyToken(client);
if (strchr(client->modes, 'a'))
strlcpy(client->away, DEFAULT_AWAY_MSG, sizeof(client->away));
if (Client_HasMode(client, 'a'))
client->away = strndup(DEFAULT_AWAY_MSG, CLIENT_AWAY_LEN - 1);
client->next = (POINTER *)My_Clients;
My_Clients = client;
@@ -234,14 +238,14 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
/* remove a client */
CLIENT *last, *c;
char msg[LINE_LEN];
char msg[COMMAND_LEN];
const char *txt;
assert( Client != NULL );
if( LogMsg ) txt = LogMsg;
else txt = FwdMsg;
if( ! txt ) txt = "Reason unknown.";
txt = LogMsg ? LogMsg : FwdMsg;
if (!txt)
txt = "Reason unknown";
/* netsplit message */
if( Client->type == CLIENT_SERVER ) {
@@ -281,10 +285,15 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
Destroy_UserOrService(c, txt, FwdMsg, SendQuit);
else if( c->type == CLIENT_SERVER )
{
if( c != This_Server )
{
if( c->conn_id != NONE ) Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
else Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered: %s", c->id, txt );
if (c != This_Server) {
if (c->conn_id != NONE)
Log(LOG_NOTICE|LOG_snotice,
"Server \"%s\" unregistered (connection %d): %s.",
c->id, c->conn_id, txt);
else
Log(LOG_NOTICE|LOG_snotice,
"Server \"%s\" unregistered: %s.",
c->id, txt);
}
/* inform other servers */
@@ -296,17 +305,23 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
}
else
{
if( c->conn_id != NONE )
{
if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt );
if (c->conn_id != NONE) {
if (c->id[0])
Log(LOG_NOTICE,
"Client \"%s\" unregistered (connection %d): %s.",
c->id, c->conn_id, txt);
else
Log(LOG_NOTICE,
"Client unregistered (connection %d): %s.",
c->conn_id, txt);
} else {
Log(LOG_WARNING, "Unregistered unknown client \"%s\": %s",
c->id[0] ? c->id : "(No Nick)", txt );
Log(LOG_WARNING,
"Unregistered unknown client \"%s\": %s",
c->id[0] ? c->id : "(No Nick)", txt);
}
}
free( c );
Free_Client(&c);
break;
}
last = c;
@@ -348,6 +363,27 @@ Client_SetHostname( CLIENT *Client, const char *Hostname )
} /* 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
Client_SetID( CLIENT *Client, const char *ID )
{
@@ -440,6 +476,22 @@ Client_SetFlags( CLIENT *Client, const char *Flags )
} /* 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
Client_SetAway( CLIENT *Client, const char *Txt )
{
@@ -448,7 +500,11 @@ Client_SetAway( CLIENT *Client, const char *Txt )
assert( Client != NULL );
assert( Txt != NULL );
strlcpy( Client->away, Txt, sizeof( Client->away ));
if (Client->away)
free(Client->away);
Client->away = strndup(Txt, CLIENT_AWAY_LEN - 1);
LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client),
Client_Mask(Client), Txt);
} /* Client_SetAway */
@@ -489,19 +545,11 @@ Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
} /* Client_SetIntroducer */
GLOBAL void
Client_SetOperByMe( CLIENT *Client, bool OperByMe )
{
assert( Client != NULL );
Client->oper_by_me = OperByMe;
} /* Client_SetOperByMe */
GLOBAL bool
Client_ModeAdd( CLIENT *Client, char Mode )
{
/* Set Mode.
* If Client already alread had Mode, return false.
* If Client already had Mode, return false.
* If the Mode was newly set, return true.
*/
@@ -510,7 +558,7 @@ Client_ModeAdd( CLIENT *Client, char Mode )
assert( Client != NULL );
x[0] = Mode; x[1] = '\0';
if (!strchr( Client->modes, x[0])) {
if (!Client_HasMode(Client, x[0])) {
strlcat( Client->modes, x, sizeof( Client->modes ));
return true;
}
@@ -545,13 +593,14 @@ Client_ModeDel( CLIENT *Client, char Mode )
} /* Client_ModeDel */
/**
* Search CLIENT structure of a given nick name.
*
* @return Pointer to CLIENT structure or NULL if not found.
*/
GLOBAL CLIENT *
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;
CLIENT *c = NULL;
UINT32 search_hash;
@@ -572,7 +621,39 @@ Client_Search( const char *Nick )
c = (CLIENT *)c->next;
}
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;
}
/**
@@ -699,8 +780,6 @@ Client_HostnameCloaked(CLIENT *Client)
* 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.
* 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
* @return Pointer to client hostname
@@ -715,13 +794,28 @@ Client_HostnameDisplayed(CLIENT *Client)
return Client_Hostname(Client);
/* Use an already saved cloaked hostname, if there is one */
if (Client->cloaked[0])
if (Client->cloaked)
return Client->cloaked;
Client_UpdateCloakedHostname(Client, NULL, NULL);
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.
*
@@ -736,25 +830,32 @@ GLOBAL void
Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin,
const char *Hostname)
{
static char Cloak_Buffer[CLIENT_HOST_LEN];
char Cloak_Buffer[CLIENT_HOST_LEN];
assert(Client != NULL);
if (!Origin)
Origin = Client_ThisServer();
if (!Client->cloaked) {
Client->cloaked = malloc(CLIENT_HOST_LEN);
if (!Client->cloaked)
return;
}
if (!Hostname) {
/* Generate new cloaked hostname */
if (*Conf_CloakHostModeX) {
strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
strlcpy(Cloak_Buffer, Client->host,
sizeof(Cloak_Buffer));
strlcat(Cloak_Buffer, Conf_CloakHostSalt,
CLIENT_HOST_LEN);
snprintf(Client->cloaked, sizeof(Client->cloaked),
sizeof(Cloak_Buffer));
snprintf(Client->cloaked, CLIENT_HOST_LEN,
Conf_CloakHostModeX, Hash(Cloak_Buffer));
} else
strlcpy(Client->cloaked, Client_ID(Client->introducer),
sizeof(Client->cloaked));
CLIENT_HOST_LEN);
} else
strlcpy(Client->cloaked, Hostname, sizeof(Client->cloaked));
strlcpy(Client->cloaked, Hostname, CLIENT_HOST_LEN);
LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"",
Client_ID(Client), Client->cloaked);
@@ -780,14 +881,6 @@ Client_Flags( CLIENT *Client )
} /* Client_Flags */
GLOBAL bool
Client_OperByMe( CLIENT *Client )
{
assert( Client != NULL );
return Client->oper_by_me;
} /* Client_OperByMe */
GLOBAL int
Client_Hops( CLIENT *Client )
{
@@ -905,6 +998,14 @@ Client_HasMode( CLIENT *Client, char Mode )
} /* Client_HasMode */
GLOBAL bool
Client_HasFlag( CLIENT *Client, char Flag )
{
assert( Client != NULL );
return strchr( Client->flags, Flag ) != NULL;
} /* Client_HasFlag */
GLOBAL char *
Client_Away( CLIENT *Client )
{
@@ -913,6 +1014,14 @@ Client_Away( CLIENT *Client )
} /* Client_Away */
GLOBAL char *
Client_AccountName(CLIENT *Client)
{
assert(Client != NULL);
return Client->account_name;
}
/**
* Make sure that a given nickname is valid.
*
@@ -931,11 +1040,11 @@ Client_CheckNick(CLIENT *Client, char *Nick)
if (!Client_IsValidNick(Nick)) {
if (strlen(Nick ) >= Conf_MaxNickLength)
IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG,
IRC_WriteErrClient(Client, ERR_NICKNAMETOOLONG_MSG,
Client_ID(Client), Nick,
Conf_MaxNickLength - 1);
else
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
Client_ID(Client), Nick);
return false;
}
@@ -944,7 +1053,7 @@ Client_CheckNick(CLIENT *Client, char *Nick)
&& Client_Type(Client) != CLIENT_SERVICE) {
/* Make sure that this isn't a restricted/forbidden nickname */
if (Conf_NickIsBlocked(Nick)) {
IRC_WriteStrClient(Client, ERR_FORBIDDENNICKNAME_MSG,
IRC_WriteErrClient(Client, ERR_FORBIDDENNICKNAME_MSG,
Client_ID(Client), Nick);
return false;
}
@@ -952,7 +1061,7 @@ Client_CheckNick(CLIENT *Client, char *Nick)
/* Nickname already registered? */
if (Client_Search(Nick)) {
IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
IRC_WriteErrClient(Client, ERR_NICKNAMEINUSE_MSG,
Client_ID(Client), Nick);
return false;
}
@@ -973,7 +1082,8 @@ Client_CheckID( CLIENT *Client, char *ID )
/* ID too long? */
if (strlen(ID) > CLIENT_ID_LEN) {
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID(Client), ID);
IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
Client_ID(Client), ID);
return false;
}
@@ -1071,7 +1181,8 @@ Client_OperCount( void )
c = My_Clients;
while( c )
{
if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
if (c && c->type == CLIENT_USER && Client_HasMode(c, 'o' ))
cnt++;
c = (CLIENT *)c->next;
}
return cnt;
@@ -1278,11 +1389,14 @@ MyCount( CLIENT_TYPE Type )
} /* MyCount */
/**
* Allocate and initialize new CLIENT strcuture.
*
* @return Pointer to CLIENT structure or NULL on error.
*/
static CLIENT *
New_Client_Struct( void )
{
/* Neue CLIENT-Struktur pre-initialisieren */
CLIENT *c;
c = (CLIENT *)malloc( sizeof( CLIENT ));
@@ -1296,14 +1410,34 @@ New_Client_Struct( void )
c->type = CLIENT_UNKNOWN;
c->conn_id = NONE;
c->oper_by_me = false;
c->hops = -1;
c->token = -1;
c->mytoken = -1;
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
Generate_MyToken( CLIENT *Client )
@@ -1317,7 +1451,7 @@ Generate_MyToken( CLIENT *Client )
{
if( c->mytoken == token )
{
/* Das Token wurde bereits vergeben */
/* The token is already in use */
token++;
c = My_Clients;
continue;
@@ -1424,7 +1558,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
if(Client->conn_id != NONE) {
/* Local (directly connected) client */
Log(LOG_NOTICE,
"%s \"%s\" unregistered (connection %d): %s",
"%s \"%s\" unregistered (connection %d): %s.",
Client_TypeText(Client), Client_Mask(Client),
Client->conn_id, Txt);
Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]",
@@ -1442,7 +1576,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
}
} else {
/* Remote client */
LogDebug("%s \"%s\" unregistered: %s",
LogDebug("%s \"%s\" unregistered: %s.",
Client_TypeText(Client), Client_Mask(Client), Txt);
if(SendQuit) {
@@ -1468,9 +1602,6 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
/**
* 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.
@@ -1479,43 +1610,100 @@ static void
cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *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;
char *modes, *user, *host;
modes = Client_Modes(c);
user = Client_User(c) ? Client_User(c) : "-";
host = Client_Hostname(c) ? Client_Hostname(c) : "-";
modes = Client_Modes(User);
user = Client_User(User) ? Client_User(User) : "-";
host = Client_Hostname(User) ? Client_Hostname(User) : "-";
conn = Client_Conn(To);
conn = Client_Conn(Client);
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);
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), user, host,
Client_ID(Client_Introducer(User)),
Client_Info(User)))
return DISCONNECTED;
if (modes[0]) {
if (! Conn_WriteStr(conn, ":%s MODE %s +%s",
Client_ID(User), Client_ID(User),
modes))
return DISCONNECTED;
}
} 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));
if (Client_Type(User) == CLIENT_SERVICE
&& Client_HasFlag(Client, 'S')) {
if (!IRC_WriteStrClientPrefix(Client, Prefix,
"SERVICE %s %d * +%s %d :%s",
Client_Mask(User),
Client_MyToken(Client_Introducer(User)),
modes, Client_Hops(User) + 1,
Client_Info(User)))
return DISCONNECTED;
} else {
if (!IRC_WriteStrClientPrefix(Client, Prefix,
"NICK %s %d %s %s %d +%s :%s",
Client_ID(User), Client_Hops(User) + 1,
user, host,
Client_MyToken(Client_Introducer(User)),
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

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de)
* 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
@@ -17,19 +17,20 @@
* Client management (header)
*/
#define CLIENT_UNKNOWN 1 /* connection of unknown type */
#define CLIENT_GOTPASS 2 /* client did send PASS */
#define CLIENT_GOTNICK 4 /* client did send NICK */
#define CLIENT_GOTUSER 8 /* client did send USER */
#define CLIENT_USER 16 /* client is an IRC user */
#define CLIENT_SERVER 32 /* client is a server */
#define CLIENT_SERVICE 64 /* client is a service */
#define CLIENT_UNKNOWNSERVER 128 /* unregistered server connection */
#define CLIENT_GOTPASS_2813 256 /* client did send PASS, RFC 2813 style */
#define CLIENT_UNKNOWN 0x0001 /* connection of unknown type */
#define CLIENT_GOTPASS 0x0002 /* client did send PASS */
#define CLIENT_GOTNICK 0x0004 /* client did send NICK */
#define CLIENT_GOTUSER 0x0008 /* client did send USER */
#define CLIENT_USER 0x0010 /* client is an IRC user */
#define CLIENT_SERVER 0x0020 /* client is a server */
#define CLIENT_SERVICE 0x0040 /* client is a service */
#define CLIENT_UNKNOWNSERVER 0x0080 /* unregistered server connection */
#define CLIENT_GOTPASS_2813 0x0100 /* client did send PASS, RFC 2813 style */
#ifndef STRICT_RFC
# define CLIENT_WAITAUTHPING 512 /* waiting for AUTH PONG from client */
# define CLIENT_WAITAUTHPING 0x0200 /* waiting for AUTH PONG from client */
#endif
#define CLIENT_WAITCAPEND 1024 /* waiting for "CAP END" command */
#define CLIENT_WAITCAPEND 0x0400 /* waiting for "CAP END" command */
#define CLIENT_ANY 0xFFFF
#define CLIENT_TYPE int
@@ -48,7 +49,8 @@ typedef struct _CLIENT
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) */
char host[CLIENT_HOST_LEN]; /* hostname of the client */
char cloaked[CLIENT_HOST_LEN]; /* cloaked hostname of the client */
char *cloaked; /* cloaked hostname of the client */
char *ipa_text; /* textual representaton of IP address */
char user[CLIENT_USER_LEN]; /* user name ("login") */
#if defined(PAM) && defined(IDENTAUTH)
char orig_user[CLIENT_USER_LEN];/* user name supplied by USER command */
@@ -56,9 +58,9 @@ typedef struct _CLIENT
char info[CLIENT_INFO_LEN]; /* long user name (user) / info text (server) */
char modes[CLIENT_MODE_LEN]; /* client modes */
int hops, token, mytoken; /* "hops" and "Token" (see SERVER command) */
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 *away; /* AWAY text (valid if mode 'a' is set) */
char flags[CLIENT_FLAGS_LEN]; /* flags of the client */
char *account_name; /* login account (for services) */
int capabilities; /* enabled IRC capabilities */
} CLIENT;
@@ -93,7 +95,10 @@ GLOBAL CLIENT *Client_ThisServer PARAMS(( void ));
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_SearchServer PARAMS(( const char *ID ));
GLOBAL CLIENT *Client_First PARAMS(( void ));
GLOBAL CLIENT *Client_Next PARAMS(( CLIENT *c ));
@@ -110,21 +115,24 @@ GLOBAL char *Client_OrigUser PARAMS(( CLIENT *Client ));
GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client ));
GLOBAL char *Client_HostnameCloaked 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_Flags 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_Token PARAMS(( CLIENT *Client ));
GLOBAL int Client_MyToken PARAMS(( CLIENT *Client ));
GLOBAL CLIENT *Client_TopServer PARAMS(( CLIENT *Client ));
GLOBAL CLIENT *Client_NextHop 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 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_SetIPAText PARAMS(( CLIENT *Client, const char *IPAText ));
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_SetOrigUser PARAMS(( CLIENT *Client, const char *User ));
@@ -132,11 +140,11 @@ GLOBAL void Client_SetInfo PARAMS(( CLIENT *Client, const char *Info ));
GLOBAL void Client_SetType PARAMS(( CLIENT *Client, int Type ));
GLOBAL void Client_SetHops PARAMS(( CLIENT *Client, int Hops ));
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_SetFlags PARAMS(( CLIENT *Client, const char *Flags ));
GLOBAL void Client_SetIntroducer PARAMS(( CLIENT *Client, CLIENT *Introducer ));
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_ModeDel PARAMS(( CLIENT *Client, char Mode ));

View File

@@ -37,11 +37,12 @@ struct ConnSSL_State {
void *cookie; /* pointer to server configuration structure
(for outgoing connections), or NULL. */
#endif
char *fingerprint;
};
#endif
bool ConnSSL_InitLibrary(void);
GLOBAL bool ConnSSL_InitLibrary PARAMS((void));
#endif /* conf_ssl_h */

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -75,6 +75,7 @@ struct SSLOptions {
char *DHFile; /**< File containing DH parameters */
array ListenPorts; /**< Array of listening SSL ports */
array KeyFilePassword; /**< Key file password */
char *CipherList; /**< Set SSL cipher list to use */
};
#endif
@@ -111,6 +112,9 @@ GLOBAL char Conf_ServerAdminMail[CLIENT_INFO_LEN];
/** Message of the day (MOTD) of this server */
GLOBAL array Conf_Motd;
/** Help text of this server */
GLOBAL array Conf_Helptext;
/** Array of ports this server should listen on */
GLOBAL array Conf_ListenPorts;
@@ -145,8 +149,8 @@ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS];
/** Array of pre-defined channels */
GLOBAL array Conf_Channels;
/** Flag indicating if only pre-defined channels are allowed (true) or not */
GLOBAL bool Conf_PredefChannelsOnly;
/** String containing all locally allowed channel prefixes for new channels */
GLOBAL char Conf_AllowedChannelTypes[8];
/** Flag indicating if IRC operators are allowed to always use MODE (true) */
GLOBAL bool Conf_OperCanMode;
@@ -199,6 +203,9 @@ GLOBAL bool Conf_PAMIsOptional;
/** Disable all CTCP commands except for /me ? */
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,
* if they have an ipv6 address? (default yes)
@@ -208,6 +215,9 @@ GLOBAL bool Conf_ConnectIPv6;
/** Try to connect to remote systems using the IPv4 protocol (true) */
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 */
GLOBAL int Conf_MaxConnections;
@@ -253,6 +263,10 @@ GLOBAL bool Conf_AddServer PARAMS(( const char *Name, UINT16 Port, const char *H
GLOBAL bool Conf_NickIsService PARAMS((int ConfServer, const char *Nick));
GLOBAL bool Conf_NickIsBlocked PARAMS((const char *Nick));
#ifdef SSL_SUPPORT
GLOBAL bool Conf_SSLInUse PARAMS((void));
#endif
/* Password required by WEBIRC command */
GLOBAL char Conf_WebircPwd[CLIENT_PASS_LEN];

View File

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

View File

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

View File

@@ -54,11 +54,16 @@ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
#define DH_BITS 2048
#define DH_BITS_MIN 1024
#define MAX_HASH_SIZE 64 /* from gnutls-int.h */
static gnutls_certificate_credentials_t x509_cred;
static gnutls_dh_params_t dh_params;
static gnutls_priority_t priorities_cache;
static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
#endif
#define SHA256_STRING_LEN (32 * 2 + 1)
static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
@@ -109,17 +114,26 @@ out:
#ifdef HAVE_LIBSSL
/**
* Log OpenSSL error message.
*
* @param msg The error message.
* @param info Additional information text or NULL.
*/
static void
LogOpenSSLError( const char *msg, const char *msg2 )
LogOpenSSLError(const char *error, const char *info)
{
unsigned long err = ERR_get_error();
char * errmsg = err ? ERR_error_string(err, NULL) : "Unable to determine error";
char * errmsg = err
? ERR_error_string(err, NULL)
: "Unable to determine error";
if (!msg) msg = "SSL Error";
if (msg2)
Log( LOG_ERR, "%s: %s: %s", msg, msg2, errmsg);
assert(error != NULL);
if (info)
Log(LOG_ERR, "%s: %s (%s)", error, info, errmsg);
else
Log( LOG_ERR, "%s: %s", msg, errmsg);
Log(LOG_ERR, "%s: %s", error, errmsg);
}
@@ -138,13 +152,20 @@ pem_passwd_cb(char *buf, int size, int rwflag, void *password)
LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
assert(passlen >= 0);
if (passlen <= 0) {
Log(LOG_ERR, "pem_passwd_cb: password required, but not set");
Log(LOG_ERR, "PEM password required but not set [in pem_passwd_cb()]!");
return 0;
}
size = passlen > size ? size : passlen;
memcpy(buf, (char *)(array_start(pass)), size);
return size;
}
static int
Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
{
return 1;
}
#endif
@@ -166,7 +187,7 @@ Load_DH_params(void)
}
dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
if (!dh_params) {
Log(LOG_ERR, "%s: PEM_read_DHparams failed!",
Log(LOG_ERR, "%s: Failed to read SSL DH parameters!",
Conf_SSLOptions.DHFile);
ret = false;
}
@@ -180,7 +201,8 @@ Load_DH_params(void)
err = gnutls_dh_params_init(&tmp_dh_params);
if (err < 0) {
Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s",
gnutls_strerror(err));
return false;
}
if (Conf_SSLOptions.DHFile) {
@@ -193,7 +215,9 @@ Load_DH_params(void)
if (err == 0)
need_dhgenerate = false;
else
Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
Log(LOG_ERR,
"Failed to initialize SSL DH parameters: %s",
gnutls_strerror(err));
memset(dhparms.data, 0, size);
free(dhparms.data);
@@ -205,7 +229,8 @@ Load_DH_params(void)
DH_BITS);
err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
if (err < 0) {
Log(LOG_ERR, "gnutls_dh_params_generate2: %s", gnutls_strerror(err));
Log(LOG_ERR, "Failed to generate SSL DH parameters: %s",
gnutls_strerror(err));
return false;
}
}
@@ -223,6 +248,10 @@ void ConnSSL_Free(CONNECTION *c)
SSL_shutdown(ssl);
SSL_free(ssl);
c->ssl_state.ssl = NULL;
if (c->ssl_state.fingerprint) {
free(c->ssl_state.fingerprint);
c->ssl_state.fingerprint = NULL;
}
}
#endif
#ifdef HAVE_LIBGNUTLS
@@ -241,8 +270,10 @@ void ConnSSL_Free(CONNECTION *c)
bool
ConnSSL_InitLibrary( void )
{
if (!array_bytes(&Conf_SSLOptions.ListenPorts))
if (!Conf_SSLInUse()) {
LogDebug("SSL not in use, skipping initialization.");
return true;
}
#ifdef HAVE_LIBSSL
SSL_CTX *newctx;
@@ -255,8 +286,10 @@ ConnSSL_InitLibrary( void )
if (!RAND_status()) {
Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
/*
* it is probably best to fail and let the user install EGD or 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";
* it is probably best to fail and let the user install EGD or
* 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";
* so it makes little sense to deal with PRNGD seeding ourselves.
*/
array_free(&Conf_SSLOptions.ListenPorts);
@@ -265,7 +298,7 @@ ConnSSL_InitLibrary( void )
newctx = SSL_CTX_new(SSLv23_method());
if (!newctx) {
LogOpenSSLError("SSL_CTX_new()", NULL);
LogOpenSSLError("Failed to create SSL context", NULL);
array_free(&Conf_SSLOptions.ListenPorts);
return false;
}
@@ -273,8 +306,16 @@ ConnSSL_InitLibrary( void )
if (!ConnSSL_LoadServerKey_openssl(newctx))
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_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 = newctx;
Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
@@ -287,22 +328,37 @@ out:
#ifdef HAVE_LIBGNUTLS
int err;
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;
}
err = gnutls_global_init();
if (err) {
Log(LOG_ERR, "gnutls_global_init(): %s", gnutls_strerror(err));
array_free(&Conf_SSLOptions.ListenPorts);
return false;
Log(LOG_ERR, "Failed to initialize GnuTLS: %s",
gnutls_strerror(err));
goto out;
}
if (!ConnSSL_LoadServerKey_gnutls()) {
array_free(&Conf_SSLOptions.ListenPorts);
return false;
if (!ConnSSL_LoadServerKey_gnutls())
goto out;
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;
return true;
out:
array_free(&Conf_SSLOptions.ListenPorts);
return false;
#endif
}
@@ -316,7 +372,8 @@ ConnSSL_LoadServerKey_gnutls(void)
err = gnutls_certificate_allocate_credentials(&x509_cred);
if (err < 0) {
Log(LOG_ERR, "gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
Log(LOG_ERR, "Failed to allocate certificate credentials: %s",
gnutls_strerror(err));
return false;
}
@@ -328,7 +385,7 @@ ConnSSL_LoadServerKey_gnutls(void)
if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
Log(LOG_WARNING,
"Ignoring KeyFilePassword: Not supported by GNUTLS.");
"Ignoring SSL \"KeyFilePassword\": Not supported by GnuTLS.");
if (!Load_DH_params())
return false;
@@ -336,8 +393,11 @@ ConnSSL_LoadServerKey_gnutls(void)
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);
if (err < 0) {
Log(LOG_ERR, "gnutls_certificate_set_x509_key_file (cert %s, key %s): %s",
cert_file, Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)", gnutls_strerror(err));
Log(LOG_ERR,
"Failed to set certificate key file (cert %s, key %s): %s",
cert_file,
Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)",
gnutls_strerror(err));
return false;
}
return true;
@@ -362,26 +422,26 @@ ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
LogOpenSSLError("SSL_CTX_use_PrivateKey_file", Conf_SSLOptions.KeyFile);
LogOpenSSLError("Failed to add private key", Conf_SSLOptions.KeyFile);
return false;
}
cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
LogOpenSSLError("SSL_CTX_use_certificate_file", cert_key);
LogOpenSSLError("Failed to load certificate chain", cert_key);
return false;
}
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
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;
}
if (Load_DH_params()) {
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 */
DH_free(dh_params);
dh_params = NULL;
@@ -395,31 +455,39 @@ static bool
ConnSSL_Init_SSL(CONNECTION *c)
{
int ret;
LogDebug("Initializing SSL ...");
assert(c != NULL);
#ifdef HAVE_LIBSSL
if (!ssl_ctx) {
Log(LOG_ERR, "Cannot init ssl_ctx: OpenSSL initialization failed at startup");
Log(LOG_ERR,
"Can't initialize SSL context, OpenSSL initialization failed at startup!");
return false;
}
assert(c->ssl_state.ssl == NULL);
assert(c->ssl_state.fingerprint == NULL);
c->ssl_state.ssl = SSL_new(ssl_ctx);
if (!c->ssl_state.ssl) {
LogOpenSSLError("SSL_new()", NULL);
LogOpenSSLError("Failed to create SSL structure", NULL);
return false;
}
Conn_OPTION_ADD(c, CONN_SSL);
ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
if (ret != 1) {
LogOpenSSLError("SSL_set_fd()", NULL);
LogOpenSSLError("Failed to set SSL file descriptor", NULL);
ConnSSL_Free(c);
return false;
}
#endif
#ifdef HAVE_LIBGNUTLS
ret = gnutls_set_default_priority(c->ssl_state.gnutls_session);
if (ret < 0) {
Log(LOG_ERR, "gnutls_set_default_priority: %s", gnutls_strerror(ret));
Conn_OPTION_ADD(c, CONN_SSL);
ret = gnutls_priority_set(c->ssl_state.gnutls_session, priorities_cache);
if (ret != GNUTLS_E_SUCCESS) {
Log(LOG_ERR, "Failed to set GnuTLS session priorities: %s",
gnutls_strerror(ret));
ConnSSL_Free(c);
return false;
}
@@ -429,16 +497,20 @@ ConnSSL_Init_SSL(CONNECTION *c)
* 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
*/
gnutls_transport_set_ptr(c->ssl_state.gnutls_session, (gnutls_transport_ptr_t) (long) c->sock);
ret = gnutls_credentials_set(c->ssl_state.gnutls_session, GNUTLS_CRD_CERTIFICATE, x509_cred);
if (ret < 0) {
Log(LOG_ERR, "gnutls_credentials_set: %s", gnutls_strerror(ret));
gnutls_transport_set_ptr(c->ssl_state.gnutls_session,
(gnutls_transport_ptr_t) (long) c->sock);
gnutls_certificate_server_set_request(c->ssl_state.gnutls_session,
GNUTLS_CERT_REQUEST);
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);
return false;
}
gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
#endif
Conn_OPTION_ADD(c, CONN_SSL);
return true;
}
@@ -452,7 +524,8 @@ ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
if (err) {
Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
Log(LOG_ERR, "Failed to initialize new SSL session: %s",
gnutls_strerror(err));
return false;
}
#endif
@@ -468,16 +541,23 @@ ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
}
/*
Check an Handle Error return code after failed calls to ssl/tls functions.
OpenSSL:
SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl.
GNUTLS:
gnutlsssl_read(), gnutls_write() or gnutls_handshake().
Return: -1 on fatal error, 0 if we can try again later.
/**
* Check and handle error return codes after failed calls to SSL functions.
*
* OpenSSL:
* SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or
* SSL_write() on ssl.
*
* 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
ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
{
#ifdef HAVE_LIBSSL
int ret = SSL_ERROR_SYSCALL;
@@ -485,6 +565,7 @@ ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
int real_errno = errno;
ret = SSL_get_error(c->ssl_state.ssl, code);
switch (ret) {
case SSL_ERROR_WANT_READ:
io_event_del(c->sock, IO_WANTWRITE);
@@ -496,31 +577,33 @@ ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
case SSL_ERROR_NONE:
return 0; /* try again later */
case SSL_ERROR_ZERO_RETURN:
LogDebug("TLS/SSL connection shut down normally");
LogDebug("SSL connection shut down normally.");
break;
/*
SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT, SSL_ERROR_WANT_X509_LOOKUP
*/
case SSL_ERROR_SYSCALL:
/* SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
* and SSL_ERROR_WANT_X509_LOOKUP */
sslerr = ERR_get_error();
if (sslerr) {
Log( LOG_ERR, "%s: %s", fname, ERR_error_string(sslerr, NULL ));
Log(LOG_ERR, "SSL error: %s [in %s()]!",
ERR_error_string(sslerr, NULL), fname);
} else {
switch (code) { /* EOF that violated protocol */
case 0:
Log(LOG_ERR, "%s: Client Disconnected", fname );
Log(LOG_ERR,
"SSL error, client disconnected [in %s()]!",
fname);
break;
case -1: /* low level socket I/O error, check errno */
Log(LOG_ERR, "%s: %s", fname, strerror(real_errno));
case -1: /* low level socket I/O error, check errno */
Log(LOG_ERR, "SSL error: %s [in %s()]!",
strerror(real_errno), fname);
}
}
break;
case SSL_ERROR_SSL:
LogOpenSSLError("TLS/SSL Protocol Error", fname);
LogOpenSSLError("SSL protocol error", fname);
break;
default:
Log( LOG_ERR, "%s: Unknown error %d!", fname, ret);
Log(LOG_ERR, "Unknown SSL error %d [in %s()]!", ret, fname);
}
ConnSSL_Free(c);
return -1;
@@ -540,7 +623,8 @@ ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
default:
assert(code < 0);
if (gnutls_error_is_fatal(code)) {
Log(LOG_ERR, "%s: %s", fname, gnutls_strerror(code));
Log(LOG_ERR, "SSL error: %s [%s].",
gnutls_strerror(code), fname);
ConnSSL_Free(c);
return -1;
}
@@ -589,11 +673,11 @@ ConnSSL_Accept( CONNECTION *c )
#ifdef HAVE_LIBGNUTLS
int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
if (err) {
Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
Log(LOG_ERR, "Failed to initialize new SSL session: %s",
gnutls_strerror(err));
return false;
}
#endif
LogDebug("ConnSSL_Accept: Initializing SSL data");
if (!ConnSSL_Init_SSL(c))
return -1;
}
@@ -612,6 +696,80 @@ ConnSSL_Connect( CONNECTION *c )
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 */
static int
@@ -632,6 +790,8 @@ ConnectAccept( CONNECTION *c, bool connect)
if (ret)
return ConnSSL_HandleError(c, ret, "gnutls_handshake");
#endif /* _GNUTLS */
(void)ConnSSL_InitCertFp(c);
Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
ConnSSL_LogCertInfo(c);
@@ -723,6 +883,19 @@ ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
#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
bool

View File

@@ -26,6 +26,9 @@ 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 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 /* conn_ssl_h */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -82,6 +82,8 @@
#define MAX_COMMANDS_SERVER_MIN 10
#define MAX_COMMANDS_SERVICE 10
#define SD_LISTEN_FDS_START 3
static bool Handle_Write PARAMS(( CONN_ID Idx ));
static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
@@ -119,6 +121,44 @@ 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_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);
#ifdef HAVE_UNSETENV
unsetenv("LISTEN_FDS");
#endif
return count;
}
/**
* IO callback for listening sockets: handle new connections. This callback
@@ -184,7 +224,7 @@ cb_connserver(int sock, UNUSED short what)
if (server < 0) {
Log(LOG_ERR, "Connection on socket %d to \"%s\" aborted!",
sock, My_Connections[idx].host);
Conn_Close(idx, "Connection aborted!", NULL, false);
Conn_Close(idx, "Connection aborted", NULL, false);
return;
}
@@ -205,7 +245,7 @@ cb_connserver(int sock, UNUSED short what)
My_Connections[idx].host, Conf_Server[server].port,
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])) {
/* more addresses to try... */
@@ -282,7 +322,7 @@ cb_connserver_login_ssl(int sock, short unused)
return;
case -1:
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;
}
@@ -329,13 +369,13 @@ cb_clientserver(int sock, short what)
#ifdef SSL_SUPPORT
/**
* IO callback for established SSL-enabled client and server connections.
* IO callback for new SSL-enabled client and server connections.
*
* @param sock Socket descriptor.
* @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...).
*/
static void
cb_clientserver_ssl(int sock, short what)
cb_clientserver_ssl(int sock, UNUSED short what)
{
CONN_ID idx = Socket2Index(sock);
@@ -352,14 +392,11 @@ cb_clientserver_ssl(int sock, short what)
case 0:
return; /* EAGAIN: callback will be invoked again by IO layer */
default:
Conn_Close(idx, "SSL accept error, closing socket", "SSL accept error", false);
Conn_Close(idx,
"SSL accept error, closing socket", "SSL accept error",
false);
return;
}
if (what & IO_WANTREAD)
Read_Request(idx);
if (what & IO_WANTWRITE)
Handle_Write(idx);
io_event_setcb(sock, cb_clientserver); /* SSL handshake completed */
}
@@ -367,14 +404,13 @@ cb_clientserver_ssl(int sock, short what)
/**
* Initialize connecion module.
* Initialize connection module.
*/
GLOBAL void
Conn_Init( void )
{
CONN_ID i;
/* Speicher fuer Verbindungs-Pool anfordern */
Pool_Size = CONNECTION_POOL;
if ((Conf_MaxConnections > 0) &&
(Pool_Size > Conf_MaxConnections))
@@ -454,7 +490,7 @@ Conn_CloseAllSockets(int ExceptOf)
* @returns Number of listening sockets created.
*/
static unsigned int
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
Init_Listeners(array *a, const char *listen_addr, void (*func)(int,short))
{
unsigned int created = 0;
size_t len;
@@ -470,8 +506,9 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
continue;
}
if (!io_event_create( fd, IO_WANTREAD, func )) {
Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
fd, (unsigned int) *port, strerror(errno));
Log(LOG_ERR,
"io_event_create(): Can't add fd %d (port %u): %s!",
fd, (unsigned int) *port, strerror(errno));
close(fd);
port++;
continue;
@@ -493,14 +530,76 @@ Conn_InitListeners( void )
{
/* Initialize ports on which the server should accept connections */
unsigned int created = 0;
char *copy, *listen_addr;
char *af_str, *copy, *listen_addr;
int count, fd, i, addr_len;
ng_ipaddr_t addr;
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 */
copy = strdup(Conf_ListenAddress);
if (!copy) {
Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress,
strerror(errno));
return 0;
}
listen_addr = strtok(copy, ",");
@@ -508,9 +607,11 @@ Conn_InitListeners( void )
while (listen_addr) {
ngt_TrimStr(listen_addr);
if (*listen_addr) {
created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
created += Init_Listeners(&Conf_ListenPorts,
listen_addr, cb_listen);
#ifdef SSL_SUPPORT
created += ports_initlisteners(&Conf_SSLOptions.ListenPorts, listen_addr, cb_listen_ssl);
created += Init_Listeners(&Conf_SSLOptions.ListenPorts,
listen_addr, cb_listen_ssl);
#endif
}
@@ -537,7 +638,12 @@ Conn_ExitListeners( void )
int *fd;
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));
if (arraylen < 1)
return;
Log(LOG_INFO,
"Shutting down all listening sockets (%d total) ...", arraylen);
fd = array_start(&My_Listeners);
@@ -568,7 +674,7 @@ InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port
ret = ng_ipaddr_init(addr, listen_addrstr, Port);
if (!ret) {
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);
}
return ret;
@@ -620,8 +726,9 @@ NewListener(const char *listen_addr, UINT16 Port)
af = ng_ipaddr_af(&addr);
sock = socket(af, SOCK_STREAM, 0);
if( sock < 0 ) {
Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
if (sock < 0) {
Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af,
strerror(errno));
return -1;
}
@@ -631,22 +738,23 @@ NewListener(const char *listen_addr, UINT16 Port)
return -1;
if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) {
Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s",
ng_ipaddr_tostr(&addr), Port, strerror(errno));
Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s!",
ng_ipaddr_tostr(&addr), Port, strerror(errno));
close(sock);
return -1;
}
if( listen( sock, 10 ) != 0 ) {
Log( LOG_CRIT, "Can't listen on socket: %s!", strerror( errno ));
close( sock );
if (listen(sock, 10) != 0) {
Log(LOG_CRIT, "Can't listen on socket: %s!", strerror(errno));
close(sock);
return -1;
}
/* keep fd in list so we can close it when ngircd restarts/shuts down */
if (!array_catb( &My_Listeners,(char*) &sock, sizeof(int) )) {
Log( LOG_CRIT, "Can't add socket to My_Listeners array: %s!", strerror( errno ));
close( sock );
if (!array_catb(&My_Listeners, (char *)&sock, sizeof(int))) {
Log(LOG_CRIT, "Can't add socket to My_Listeners array: %s!",
strerror(errno));
close(sock);
return -1;
}
@@ -746,8 +854,7 @@ Conn_Handler(void)
/* Look for non-empty read buffers ... */
for (i = 0; i < Pool_Size; i++) {
if ((My_Connections[i].sock > NONE)
&& (array_bytes(&My_Connections[i].rbuf) > 0)
&& (My_Connections[i].delaytime <= t)) {
&& (array_bytes(&My_Connections[i].rbuf) > 0)) {
/* ... and try to handle the received data */
bytes_processed = Handle_Buffer(i);
/* if we processed data, and there might be
@@ -817,7 +924,7 @@ Conn_Handler(void)
* which is the granularity with witch we handle "penalty
* times" for example.
* Note: tv_sec/usec are undefined(!) after io_dispatch()
* returns, so we have to set it beforce each call to it! */
* returns, so we have to set it before each call to it! */
tv.tv_usec = 0;
tv.tv_sec = 1;
@@ -830,6 +937,15 @@ Conn_Handler(void)
PACKAGE_NAME);
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)
@@ -893,7 +1009,7 @@ va_dcl
*
* 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
* the originator (any more). The "old" behaviour of blaming
* the originator (any more). The "old" behavior of blaming
* the receiver ("next hop") is a bad idea (it could be just
* an other server only routing the message!), so the only
* option left is to shorten the string and to hope that the
@@ -1067,8 +1183,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
/* Is this link already shutting down? */
if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) {
/* Conn_Close() has been called recursively for this link;
* probabe reason: Handle_Write() failed -- see below. */
LogDebug("Recursive request to close connection: %d", Idx );
* probable reason: Handle_Write() failed -- see below. */
LogDebug("Recursive request to close connection %d!", Idx );
return;
}
@@ -1078,7 +1194,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
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);
/* Search client, if any */
@@ -1114,7 +1230,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
c = Conn_GetClient( Idx );
#ifdef SSL_SUPPORT
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
Log(LOG_INFO, "SSL connection %d shutting down ...", Idx);
LogDebug("SSL connection %d shutting down ...", Idx);
ConnSSL_Free(&My_Connections[Idx]);
}
#endif
@@ -1152,7 +1268,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
in_p = (int)(( in_k * 100 ) / in_z_k );
out_p = (int)(( out_k * 100 ) / out_z_k );
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,
in_k, in_z_k, in_p, out_k, out_z_k, out_p);
}
@@ -1160,7 +1276,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
#endif
{
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,
in_k, out_k);
}
@@ -1191,6 +1307,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
NumConnections--;
LogDebug("Shutdown of connection %d completed, %ld connection%s left.",
Idx, NumConnections, NumConnections != 1 ? "s" : "");
idle_t = NumConnections > 0 ? 0 : time(NULL);
} /* Conn_Close */
@@ -1334,9 +1452,14 @@ Handle_Write( CONN_ID Idx )
if (errno == EAGAIN || errno == EINTR)
return true;
Log(LOG_ERR, "Write error on connection %d (socket %d): %s!",
Idx, My_Connections[Idx].sock, strerror(errno));
Conn_Close(Idx, "Write error!", NULL, false);
if (!Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ISCLOSING))
Log(LOG_ERR,
"Write error on connection %d (socket %d): %s!",
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;
}
@@ -1500,7 +1623,7 @@ New_Connection(int Sock, UNUSED bool IsSSL)
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,
ng_ipaddr_getport(&new_addr), Sock);
Account_Connection();
@@ -1547,7 +1670,11 @@ Conn_StartLogin(CONN_ID Idx)
#endif
(void)Conn_WriteStr(Idx,
"NOTICE AUTH :*** Looking up your hostname");
(void)Handle_Write(Idx);
/* Send buffered data to the client, but break on errors
* 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,
@@ -1562,6 +1689,7 @@ static void
Account_Connection(void)
{
NumConnections++;
idle_t = 0;
if (NumConnections > NumConnectionsMax)
NumConnectionsMax = NumConnections;
LogDebug("Total number of connections now %lu (max %lu).",
@@ -1591,7 +1719,7 @@ Socket2Index( int Sock )
/**
* Read data from the network to the read buffer. If an error occures,
* Read data from the network to the read buffer. If an error occurs,
* the socket of this connection will be shut down.
*
* @param Idx Connection index.
@@ -1629,13 +1757,10 @@ Read_Request( CONN_ID Idx )
#endif
len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
if (len == 0) {
Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
My_Connections[Idx].host,
(unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr),
ng_ipaddr_tostr(&My_Connections[Idx].addr));
Conn_Close(Idx,
"Socket closed!", "Client closed connection",
false);
LogDebug("Client \"%s:%u\" is closing connection %d ...",
My_Connections[Idx].host,
ng_ipaddr_tostr(&My_Connections[Idx].addr), Idx);
Conn_Close(Idx, NULL, "Client closed connection", false);
return;
}
@@ -1643,7 +1768,7 @@ Read_Request( CONN_ID Idx )
if( errno == EAGAIN ) return;
Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
Idx, My_Connections[Idx].sock, strerror(errno));
Conn_Close(Idx, "Read error!", "Client closed connection",
Conn_Close(Idx, "Read error", "Client closed connection",
false);
return;
}
@@ -1743,7 +1868,7 @@ Handle_Buffer(CONN_ID Idx)
maxcmd = (int)(Client_UserCount() / 5)
+ MAX_COMMANDS_SERVER_MIN;
/* Allow servers to handle even more commands while peering
* to speed up server login and network synchronisation. */
* to speed up server login and network synchronization. */
if (Conn_LastPing(Idx) == 0)
maxcmd *= 5;
break;
@@ -2008,6 +2133,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string");
Conf_Server[Server].conn_id = NONE;
return;
}
@@ -2022,11 +2148,14 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (new_sock < 0) {
Log(LOG_CRIT, "Can't create socket (af %d): %s!",
af_dest, strerror(errno));
Conf_Server[Server].conn_id = NONE;
return;
}
if (!Init_Socket(new_sock))
if (!Init_Socket(new_sock)) {
Conf_Server[Server].conn_id = NONE;
return;
}
/* is a bind address configured? */
res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
@@ -2042,6 +2171,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
if(( res != 0 ) && ( errno != EINPROGRESS )) {
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
close( new_sock );
Conf_Server[Server].conn_id = NONE;
return;
}
@@ -2050,12 +2180,14 @@ New_Server( int Server , ng_ipaddr_t *dest)
"Cannot allocate memory for server connection (socket %d)",
new_sock);
close( new_sock );
Conf_Server[Server].conn_id = NONE;
return;
}
if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
close(new_sock);
Conf_Server[Server].conn_id = NONE;
return;
}
@@ -2070,6 +2202,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
if (!c) {
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
io_close(new_sock);
Conf_Server[Server].conn_id = NONE;
return;
}
@@ -2237,7 +2370,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
/**
* Read results of a resolver sub-process from the pipe and update the
* apropriate connection/client structure(s): hostname and/or IDENT user name.
* appropriate connection/client structure(s): hostname and/or IDENT user name.
*
* @param r_fd File descriptor of the pipe to the sub-process.
* @param events (ignored IO specification)
@@ -2331,21 +2464,27 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
*ptr ? "" : ": ",
*ptr ? "" : identptr);
}
} else {
} else if(Conf_Ident) {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
if (Conf_NoticeAuth && Conf_Ident)
if (Conf_NoticeAuth)
(void)Conn_WriteStr(i,
"NOTICE AUTH :*** No ident response");
}
#endif
if (Conf_NoticeAuth)
(void)Handle_Write(i);
if (Conf_NoticeAuth) {
/* Send buffered data to the client, but break on
* errors because Handle_Write() would have closed
* the connection again in this case! */
if (!Handle_Write(i))
return;
}
Class_HandleServerBans(c);
}
#ifdef DEBUG
else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
else
LogDebug("Resolver: discarding result for already registered connection %d.", i);
#endif
} /* cb_Read_Resolver_Result */
@@ -2464,7 +2603,7 @@ Conn_SetAuthPing(CONN_ID Idx, long ID)
#ifdef SSL_SUPPORT
/**
* Get information about used SSL chiper.
* Get information about used SSL cipher.
*
* @param Idx Connection index number.
* @param buf Buffer for returned information text.
@@ -2496,6 +2635,45 @@ Conn_UsesSSL(CONN_ID Idx)
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

View File

@@ -139,13 +139,12 @@ GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd));
GLOBAL CLIENT* Conn_GetClient 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
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
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -24,6 +24,7 @@
#include "conn.h"
#include "channel.h"
#include "client-cap.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "log.h"
#include "login.h"
@@ -33,192 +34,14 @@
#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;
}
/* Local functions */
/**
* Set CAP negotiation status and mark client as "supports capabilities".
*
* @param Client The client to handle.
*/
void
static void
Set_CAP_Negotiation(CLIENT *Client)
{
assert(Client != NULL);
@@ -234,7 +57,7 @@ Set_CAP_Negotiation(CLIENT *Client)
* @param Args The string containing space-separated capability names.
* @return Changed capability flags or 0 on error.
*/
int
static int
Parse_CAP(int Capabilities, char *Args)
{
static char tmp[COMMAND_LEN];
@@ -275,7 +98,7 @@ Parse_CAP(int Capabilities, char *Args)
* @param Capabilities Capability flags (bitmask).
* @return Pointer to textual representation.
*/
char *
static char *
Get_CAP_String(int Capabilities)
{
static char txt[COMMAND_LEN];
@@ -288,4 +111,169 @@ Get_CAP_String(int Capabilities)
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- */

View File

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

View File

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

113
src/ngircd/irc-macros.h Normal file
View File

@@ -0,0 +1,113 @@
/*
* 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
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -51,26 +51,22 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
assert(Client != 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);
if (!prefix)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
target = Client_Search(Req->argv[0]);
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]);
LogDebug("Got \"METADATA\" command from \"%s\" for client \"%s\": \"%s=%s\".",
Client_ID(prefix), Client_ID(target),
Req->argv[1], Req->argv[2]);
/* Mark client: it has receiveda a METADATA command */
if (!strchr(Client_Flags(target), 'M')) {
/* Mark client: it has received a METADATA command */
if (!Client_HasFlag(target, 'M')) {
snprintf(new_flags, sizeof new_flags, "%sM",
Client_Flags(target));
Client_SetFlags(target, new_flags);
@@ -96,6 +92,10 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
Client_SetInfo(target, Req->argv[2]);
else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
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
Log(LOG_WARNING,
"Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!",

View File

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

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
* 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
@@ -24,6 +24,7 @@
#include "defines.h"
#include "conn.h"
#include "channel.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "lists.h"
#include "log.h"
@@ -33,6 +34,7 @@
#include "exp.h"
#include "irc-op.h"
/* Local functions */
static bool
try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel,
@@ -41,13 +43,22 @@ try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel,
CLIENT *target = Client_Search(nick);
if (!target)
return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, Client_ID(from), nick);
return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(from), nick);
Channel_Kick(peer, target, from, channel, reason);
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
IRC_KICK(CLIENT *Client, REQUEST *Req)
{
@@ -60,9 +71,7 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
assert( Client != NULL );
assert( Req != NULL );
if ((Req->argc < 2) || (Req->argc > 3))
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
while (*itemList) {
if (*itemList == ',') {
@@ -81,15 +90,6 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
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);
currentNick = Req->argv[1];
currentChannel = Req->argv[0];
@@ -122,13 +122,20 @@ IRC_KICK(CLIENT *Client, REQUEST *Req)
nickCount--;
}
} else {
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
return true;
} /* 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
IRC_INVITE(CLIENT *Client, REQUEST *Req)
{
@@ -140,51 +147,47 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
assert( Client != NULL );
assert( Req != NULL );
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);
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
/* Search user */
target = Client_Search(Req->argv[0]);
if (!target || (Client_Type(target) != CLIENT_USER))
return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]);
return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[0]);
chan = Channel_Search(Req->argv[1]);
if (chan) {
/* Channel exists. Is the user a valid member of the channel? */
if (!Channel_IsMemberOf(chan, from))
return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Req->argv[1]);
return IRC_WriteErrClient(from, ERR_NOTONCHANNEL_MSG,
Client_ID(Client),
Req->argv[1]);
/* Is the channel "invite-disallow"? */
if (strchr(Channel_Modes(chan), 'V'))
return IRC_WriteStrClient(from, ERR_NOINVITE_MSG,
Client_ID(from), Channel_Name(chan));
if (Channel_HasMode(chan, 'V'))
return IRC_WriteErrClient(from, ERR_NOINVITE_MSG,
Client_ID(from),
Channel_Name(chan));
/* Is the channel "invite-only"? */
if (strchr(Channel_Modes(chan), 'i')) {
if (Channel_HasMode(chan, 'i')) {
/* Yes. The user must be channel owner/admin/operator/halfop! */
if (!strchr(Channel_UserModes(chan, from), 'q') &&
!strchr(Channel_UserModes(chan, from), 'a') &&
!strchr(Channel_UserModes(chan, from), 'o') &&
!strchr(Channel_UserModes(chan, from), 'h'))
return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(from), Channel_Name(chan));
if (!Channel_UserHasMode(chan, from, 'q') &&
!Channel_UserHasMode(chan, from, 'a') &&
!Channel_UserHasMode(chan, from, 'o') &&
!Channel_UserHasMode(chan, from, 'h'))
return IRC_WriteErrClient(from,
ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(from),
Channel_Name(chan));
remember = true;
}
/* Is the target user already member of the channel? */
if (Channel_IsMemberOf(chan, target))
return IRC_WriteStrClient(from, ERR_USERONCHANNEL_MSG,
Client_ID(from), Req->argv[0], Req->argv[1]);
return IRC_WriteErrClient(from, ERR_USERONCHANNEL_MSG,
Client_ID(from),
Req->argv[0], Req->argv[1]);
/* If the target user is banned on that channel: remember invite */
if (Lists_Check(Channel_GetListBans(chan), target))
@@ -192,13 +195,14 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
if (remember) {
/* We must remember this invite */
if (!Channel_AddInvite(chan, Client_Mask(target), true))
if (!Channel_AddInvite(chan, Client_MaskCloaked(target),
true))
return CONNECTED;
}
}
LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from), Req->argv[0], Req->argv[1]);
LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from),
Req->argv[0], Req->argv[1]);
/*
* RFC 2812 says:
@@ -218,7 +222,7 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
Client_ID(from), Req->argv[0], colon_if_necessary, Req->argv[1]))
return DISCONNECTED;
if (strchr(Client_Modes(target), 'a') &&
if (Client_HasMode(target, 'a') &&
!IRC_WriteStrClient(from, RPL_AWAY_MSG, Client_ID(from),
Client_ID(target), Client_Away(target)))
return DISCONNECTED;
@@ -226,5 +230,4 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
return CONNECTED;
} /* IRC_INVITE */
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -28,11 +28,14 @@
#include "conf.h"
#include "channel.h"
#include "class.h"
#include "parse.h"
#include "irc.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "lists.h"
#include "log.h"
#include "match.h"
#include "messages.h"
#include "parse.h"
#include "op.h"
#include <exp.h>
@@ -47,16 +50,13 @@ Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
{
Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s",
Client_Mask(Client), errtoken, errmsg);
IRC_SetPenalty(Client, 3);
return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
return IRC_WriteErrClient(Client, ERR_PASSWDMISMATCH_MSG,
Client_ID(Client));
} /* Bad_OperPass */
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -70,10 +70,6 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
assert( Client != 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));
op = array_start(&Conf_Opers);
for (i = 0; i < len && strcmp(op[i].name, Req->argv[0]); i++)
@@ -96,20 +92,16 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
Client_ID(Client));
}
if (!Client_OperByMe(Client))
Log(LOG_NOTICE|LOG_snotice,
"Got valid OPER from \"%s\", user is an IRC operator now.",
Client_Mask(Client));
Log(LOG_NOTICE|LOG_snotice,
"Got valid OPER for \"%s\" from \"%s\", user is an IRC operator now.",
Req->argv[0], Client_Mask(Client));
Client_SetOperByMe(Client, true);
return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client));
} /* IRC_OPER */
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -128,15 +120,6 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
if (!Op_Check(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? */
if (Req->argc > 0) {
c = Conn_First();
@@ -159,8 +142,6 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -176,11 +157,6 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
if (!Op_Check(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\" ...",
Client_Mask(Client));
IRC_WriteStrClient(Client, RPL_REHASHING_MSG, Client_ID(Client));
@@ -193,8 +169,6 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -210,11 +184,6 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
if (!Op_Check(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\" ...",
Client_Mask(Client));
NGIRCd_SignalRestart = true;
@@ -225,8 +194,6 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -239,21 +206,25 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
assert(Client != 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
&& !Client_HasMode(Client, 'o'))
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;
target = Client_ThisServer();
@@ -262,14 +233,14 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
if (Client_Type(Client) == CLIENT_SERVER && Req->prefix)
from = Client_Search(Req->prefix);
if (! from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
target = (Req->argc == 3) ? Client_Search(Req->argv[2])
: Client_Search(Req->argv[5]);
if (! target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Req->argv[0]);
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from), Req->argv[0]);
}
if (target != Client_ThisServer()) {
@@ -292,7 +263,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
switch (Req->argc) {
case 1:
if (!Conf_EnablePassiveServer(Req->argv[0]))
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from),
Req->argv[0]);
break;
@@ -301,7 +272,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
/* Connect configured server */
if (!Conf_EnableServer
(Req->argv[0], (UINT16) atoi(Req->argv[1])))
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from),
Req->argv[0]);
break;
@@ -310,7 +281,7 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
if (!Conf_AddServer
(Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2],
Req->argv[3], Req->argv[4]))
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
return IRC_WriteErrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from),
Req->argv[0]);
}
@@ -346,11 +317,6 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
if (!Op_Check(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(),
"Received DISCONNECT %s from %s",
Req->argv[0], Client_ID(Client));
@@ -364,7 +330,7 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
/* Disconnect configured server */
if (!Conf_DisableServer(Req->argv[0]))
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->argv[0]);
/* Are we still connected or were we killed, too? */
@@ -377,8 +343,6 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
/**
* 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 Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
@@ -391,15 +355,10 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
assert( Client != NULL );
assert( Req != NULL );
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
switch (Client_Type(Client)) {
case CLIENT_USER:
if (!Client_OperByMe(Client))
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
if (!Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req);
from = Client;
break;
case CLIENT_SERVER:
@@ -410,7 +369,7 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
}
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
IRC_SendWallops(Client, from, "%s", Req->argv[0]);
@@ -427,22 +386,26 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
GLOBAL bool
IRC_xLINE(CLIENT *Client, REQUEST *Req)
{
CLIENT *from;
CLIENT *from, *c, *c_next;
char reason[COMMAND_LEN], class_c;
struct list_head *list;
time_t timeout;
int class;
char class_c;
assert(Client != 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);
if (!from)
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]) {
case 'g':
case 'G':
@@ -473,8 +436,11 @@ IRC_xLINE(CLIENT *Client, REQUEST *Req)
}
} else {
/* Add new mask to list */
timeout = atol(Req->argv[1]);
if (timeout > 0)
timeout += time(NULL);
if (Class_AddMask(class, Req->argv[0],
time(NULL) + atol(Req->argv[1]),
timeout,
Req->argv[2])) {
Log(LOG_NOTICE|LOG_snotice,
"\"%s\" added \"%s\" to %c-Line list: \"%s\" (%ld seconds).",
@@ -487,6 +453,20 @@ IRC_xLINE(CLIENT *Client, REQUEST *Req)
Req->argv[0], Req->argv[1],
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
* Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
* 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
@@ -29,7 +29,6 @@
#include "conn-zip.h"
#include "conf.h"
#include "channel.h"
#include "irc-write.h"
#include "lists.h"
#include "log.h"
#include "messages.h"
@@ -37,20 +36,24 @@
#include "numeric.h"
#include "ngircd.h"
#include "irc-info.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "op.h"
#include "exp.h"
#include "irc-server.h"
/**
* Handler for the IRC command "SERVER".
* See RFC 2813 section 4.1.2.
* Handler for the IRC "SERVER" 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
IRC_SERVER( CLIENT *Client, REQUEST *Req )
{
char str[LINE_LEN];
char str[100];
CLIENT *from, *c;
int i;
@@ -59,7 +62,7 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
/* Return an error if this is not a local client */
if (Client_Conn(Client) <= NONE)
return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
return IRC_WriteErrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
Client_ID(Client), Req->command);
if (Client_Type(Client) == CLIENT_GOTPASS ||
@@ -69,17 +72,19 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
LogDebug("Connection %d: got SERVER command (new server link) ...",
Client_Conn(Client));
if (Req->argc != 2 && Req->argc != 3)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
if (Req->argc != 2 && Req->argc != 3) {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
}
/* Get configuration index of new remote server ... */
for (i = 0; i < MAX_SERVERS; i++)
if (strcasecmp(Req->argv[0], Conf_Server[i].name) == 0)
break;
/* Makre sure the remote server is configured here */
/* Make sure the remote server is configured here */
if (i >= MAX_SERVERS) {
Log(LOG_ERR,
"Connection %d: Server \"%s\" not configured here!",
@@ -149,17 +154,17 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
Client_SetType(Client, CLIENT_UNKNOWNSERVER);
#ifdef ZLIB
if (strchr(Client_Flags(Client), 'Z')
if (Client_HasFlag(Client, 'Z')
&& !Zip_InitConn(Client_Conn(Client))) {
Conn_Close(Client_Conn(Client),
"Can't inizialize compression (zlib)!",
"Can't initialize compression (zlib)!",
NULL, false );
return DISCONNECTED;
}
#endif
#ifdef IRCPLUS
if (strchr(Client_Flags(Client), 'H')) {
if (Client_HasFlag(Client, 'H')) {
LogDebug("Peer supports IRC+ extended server handshake ...");
if (!IRC_Send_ISUPPORT(Client))
return DISCONNECTED;
@@ -180,41 +185,70 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
{
/* New server is being introduced to the network */
if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc != 4) {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
/* check for existing server with same ID */
if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
if (!Client_CheckID(Client, Req->argv[0]))
return DISCONNECTED;
from = Client_Search( Req->prefix );
if( ! from )
{
if (! from) {
/* Uh, Server, that introduced the new server is unknown?! */
Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", true);
Log(LOG_ALERT,
"Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)",
Req->prefix, Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL,
"Unknown ID in prefix of SERVER", true);
return DISCONNECTED;
}
c = Client_NewRemoteServer(Client, Req->argv[0], from, atoi(Req->argv[1]), atoi(Req->argv[2]), Req->argv[3], true);
c = Client_NewRemoteServer(Client, Req->argv[0], from,
atoi(Req->argv[1]), atoi(Req->argv[2]),
Req->argv[3], true);
if (!c) {
Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", true);
Log(LOG_ALERT,
"Can't create client structure for server! (on connection %d)",
Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL,
"Can't allocate client structure for remote server",
true);
return DISCONNECTED;
}
if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) snprintf( str, sizeof( str ), "connected to %s, ", Client_ID( from ));
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": "" );
if (Client_Hops(c) > 1 && Req->prefix[0])
snprintf(str, sizeof(str), "connected to %s, ",
Client_ID(from));
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 */
IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
IRC_WriteStrServersPrefix(Client, from, "SERVER %s %d %d :%s",
Client_ID(c), Client_Hops(c) + 1,
Client_MyToken(c), Client_Info(c));
return CONNECTED;
} else
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
} else {
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
} /* 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
IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{
@@ -226,8 +260,6 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req )
assert( Client != 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 ));
strcpy( nick_out, "" );
@@ -288,15 +320,19 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req )
}
/* forward to other servers */
if( nick_out[0] != '\0' ) IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], nick_out );
if (nick_out[0] != '\0')
IRC_WriteStrServersPrefix(Client, Client_ThisServer(),
"NJOIN %s :%s", Req->argv[0], nick_out);
return CONNECTED;
} /* IRC_NJOIN */
/**
* Handler for the IRC command "SQUIT".
* See RFC 2813 section 4.1.2 and RFC 2812 section 3.1.8.
* Handler for the IRC "SQUIT" 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
IRC_SQUIT(CLIENT * Client, REQUEST * Req)
@@ -313,11 +349,6 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
&& !Client_HasMode(Client, 'o'))
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) {
from = Client_Search(Req->prefix);
if (Client_Type(from) != CLIENT_SERVER
@@ -326,7 +357,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
} else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
if (Client_Type(Client) == CLIENT_USER)
@@ -352,7 +383,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
if (Req->argv[1][0])
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));
else
strlcpy(msg, Req->argv[1], sizeof(msg));
@@ -385,7 +416,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
logmsg[0] = '\0';
if (!strchr(msg, '('))
snprintf(logmsg, sizeof(logmsg),
"%s (SQUIT from %s)", Req->argv[1],
"\"%s\" (SQUIT from %s)", Req->argv[1],
Client_ID(from));
Client_Destroy(target, logmsg[0] ? logmsg : msg,
msg, false);

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* 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
@@ -33,17 +33,58 @@
#include "exp.h"
#include "irc-write.h"
#define SEND_TO_USER 1
#define SEND_TO_SERVER 2
static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
CLIENT *Prefix, void *Buffer));
static bool Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer));
static void 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
GLOBAL bool
IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
@@ -56,27 +97,31 @@ va_dcl
#endif
{
char buffer[1000];
bool ok = CONNECTED;
va_list ap;
assert( Client != NULL );
assert( Format != NULL );
assert(Client != NULL);
assert(Format != NULL);
#ifdef PROTOTYPES
va_start( ap, Format );
va_start(ap, Format);
#else
va_start( ap );
va_start(ap);
#endif
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
/* to the client itself */
ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
return ok;
} /* IRC_WriteStrClient */
vsnprintf(buffer, 1000, Format, ap);
va_end(ap);
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
GLOBAL bool
IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
@@ -108,15 +153,24 @@ va_dcl
return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s",
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
GLOBAL bool
GLOBAL void
IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
const char *Format, ...)
#else
GLOBAL bool
GLOBAL void
IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
CLIENT *Client;
CHANNEL *Chan;
@@ -139,21 +193,27 @@ va_dcl
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
} /* IRC_WriteStrChannel */
IRC_WriteStrChannelPrefix(Client, Chan, Client_ThisServer(),
Remote, "%s", buffer);
}
/**
* send message to all clients in the same channel, but only send message
* once per remote server.
* Send a message to all client in a channel using a specific prefix.
*
* 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
GLOBAL bool
GLOBAL void
IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
bool Remote, const char *Format, ...)
#else
GLOBAL bool
GLOBAL void
IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
CLIENT *Client;
CHANNEL *Chan;
@@ -185,29 +245,36 @@ va_dcl
Conn_ClearFlags( );
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
while(cl2chan) {
c = Channel_GetClient( cl2chan );
if( ! Remote )
{
if( Client_Conn( c ) <= NONE ) c = NULL;
else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
if (!Remote) {
if (Client_Conn(c) <= NONE)
c = NULL;
else if(Client_Type(c) == CLIENT_SERVER)
c = NULL;
}
if( c ) c = Client_NextHop( c );
if(c)
c = Client_NextHop(c);
if( c && ( c != Client ))
{
if(c && c != Client) {
/* Ok, another Client */
conn = Client_Conn( c );
if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
else Conn_SetFlag( conn, SEND_TO_USER );
conn = Client_Conn(c);
if (Client_Type(c) == CLIENT_SERVER)
Conn_SetFlag(conn, SEND_TO_SERVER);
else
Conn_SetFlag(conn, SEND_TO_USER);
}
cl2chan = Channel_NextMember( Chan, cl2chan );
cl2chan = Channel_NextMember(Chan, cl2chan);
}
return Send_Marked_Connections(Prefix, buffer);
} /* IRC_WriteStrChannelPrefix */
Send_Marked_Connections(Prefix, buffer);
}
/**
* 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
GLOBAL void
IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
@@ -232,10 +299,16 @@ va_dcl
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
} /* IRC_WriteStrServers */
IRC_WriteStrServersPrefix(ExceptOf, Client_ThisServer(), "%s", buffer);
}
/**
* 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
GLOBAL void
IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
@@ -264,9 +337,17 @@ va_dcl
va_end( ap );
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
GLOBAL void
IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
@@ -297,9 +378,18 @@ va_dcl
IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
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
IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
@@ -311,24 +401,32 @@ IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
c != Client_ThisServer() && c != ExceptOf) {
/* Found a target server, do the flags match? */
if (Flag == '\0' || strchr(Client_Flags(c), Flag))
if (Flag == '\0' || Client_HasFlag(c, Flag))
callback(c, Prefix, cb_data);
}
c = Client_Next(c);
}
} /* IRC_WriteStrServersPrefixFlag */
}
/**
* send message to all clients that are in the same channels as the client sending this message.
* only send message once per reote server.
* Send a message to all "related" clients.
*
* 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
GLOBAL bool
GLOBAL void
IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
const char *Format, ...)
#else
GLOBAL bool
GLOBAL void
IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
CLIENT *Client;
CLIENT *Prefix;
@@ -384,13 +482,16 @@ va_dcl
chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
}
return Send_Marked_Connections(Prefix, buffer);
Send_Marked_Connections(Prefix, buffer);
} /* IRC_WriteStrRelatedPrefix */
/**
* 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
GLOBAL void
IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
@@ -434,23 +535,32 @@ va_dcl
}
} /* 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
IRC_SetPenalty( CLIENT *Client, time_t Seconds )
IRC_SetPenalty(CLIENT *Client, time_t Seconds)
{
CONN_ID c;
assert( Client != NULL );
assert( Seconds > 0 );
assert(Client != NULL);
assert(Seconds > 0);
if( Client_Type( Client ) == CLIENT_SERVER ) return;
if (Client_Type(Client) == CLIENT_SERVER)
return;
c = Client_Conn( Client );
if (c > NONE)
Conn_SetPenalty(c, Seconds);
c = Client_Conn(Client);
if (c <= NONE)
return;
Conn_SetPenalty(c, Seconds);
} /* IRC_SetPenalty */
static const char *
Get_Prefix(CLIENT *Target, CLIENT *Client)
{
@@ -463,19 +573,22 @@ Get_Prefix(CLIENT *Target, CLIENT *Client)
return Client_MaskCloaked(Client);
} /* Get_Prefix */
static void
cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
{
IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
} /* cb_writeStrServersPrefixFlag */
static bool
/**
* Send a message to all marked connections using a specific prefix.
*
* @param Prefix The prefix to use.
* @param Buffer The message to send.
*/
static void
Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
{
CONN_ID conn;
bool ok = CONNECTED;
assert(Prefix != NULL);
assert(Buffer != NULL);
@@ -483,17 +596,13 @@ Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
conn = Conn_First();
while (conn != NONE) {
if (Conn_Flag(conn) == SEND_TO_SERVER)
ok = Conn_WriteStr(conn, ":%s %s",
Client_ID(Prefix), Buffer);
Conn_WriteStr(conn, ":%s %s",
Client_ID(Prefix), Buffer);
else if (Conn_Flag(conn) == SEND_TO_USER)
ok = Conn_WriteStr(conn, ":%s %s",
Client_MaskCloaked(Prefix), Buffer);
if (!ok)
break;
conn = Conn_Next( conn );
Conn_WriteStr(conn, ":%s %s",
Client_MaskCloaked(Prefix), Buffer);
conn = Conn_Next(conn);
}
return ok;
}
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* 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
@@ -17,13 +17,15 @@
* 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_WriteStrClientPrefix PARAMS((CLIENT *Client, CLIENT *Prefix,
const char *Format, ...));
GLOBAL bool IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan,
GLOBAL void IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan,
bool Remote, const char *Format, ...));
GLOBAL bool IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan,
GLOBAL void IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan,
CLIENT *Prefix, bool Remote, const char *Format, ...));
GLOBAL void IRC_WriteStrServers PARAMS((CLIENT *ExceptOf,
@@ -36,7 +38,7 @@ GLOBAL void IRC_WriteStrServersPrefixFlag_CB PARAMS((CLIENT *ExceptOf,
CLIENT *Prefix, char Flag,
void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data));
GLOBAL bool IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix,
GLOBAL void IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix,
bool Remote, const char *Format, ...));
GLOBAL void IRC_SendWallops PARAMS((CLIENT *Client, CLIENT *From,

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -27,24 +27,25 @@
#include "channel.h"
#include "conn-encoding.h"
#include "defines.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "log.h"
#include "match.h"
#include "messages.h"
#include "parse.h"
#include "op.h"
#include "tool.h"
#include "exp.h"
#include "irc.h"
static char *Option_String PARAMS((CONN_ID Idx));
static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType,
bool SendErrors));
static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
char *targetMask, char *message,
bool SendErrors));
static bool Help PARAMS((CLIENT *Client, const char *Topic));
/**
* Check if a list limit is reached and inform client accordingly.
@@ -74,9 +75,15 @@ IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit,
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
IRC_ERROR( CLIENT *Client, REQUEST *Req )
IRC_ERROR(CLIENT *Client, REQUEST *Req)
{
assert( Client != NULL );
assert( Req != NULL );
@@ -102,11 +109,10 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req )
return CONNECTED;
} /* IRC_ERROR */
/**
* Handler for the IRC "KILL" command.
*
* This function implements the IRC command "KILL" wich is used to selectively
* This function implements the IRC command "KILL" which is used to selectively
* 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.
*
@@ -114,28 +120,22 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req )
* KILL command being received over the network! Client is Client_ThisServer()
* in this case, and the prefix in Req is NULL.
*
* @param Client The client from which this command has been received
* or Client_ThisServer() when generated interanlly.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
* @param Client The client from which this command has been received or
* Client_ThisServer() when generated interanlly.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_KILL( CLIENT *Client, REQUEST *Req )
IRC_KILL(CLIENT *Client, REQUEST *Req)
{
CLIENT *prefix, *c;
char reason[COMMAND_LEN], *msg;
CONN_ID my_conn, conn;
CLIENT *prefix;
char reason[COMMAND_LEN];
assert (Client != NULL);
assert (Req != NULL);
if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
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);
if (Client_Type(Client) != CLIENT_SERVER && !Op_Check(Client, Req))
return Op_NoPrivileges(Client, Req);
/* Get prefix (origin); use the client if no prefix is given. */
if (Req->prefix)
@@ -144,7 +144,8 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
prefix = Client;
/* Log a warning message and use this server as origin when the
* prefix (origin) is invalid. */
* prefix (origin) is invalid. And this is the reason why we don't
* use the _IRC_GET_SENDER_OR_RETURN_ macro above! */
if (!prefix) {
Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
Req->prefix );
@@ -153,7 +154,7 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
if (Client != Client_ThisServer())
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]);
/* Build reason string: Prefix the "reason" if the originator is a
@@ -164,74 +165,28 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
else
strlcpy(reason, Req->argv[1], sizeof(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 */
return IRC_KillClient(Client, prefix, Req->argv[0], reason);
}
/**
* Handler for the IRC command NOTICE.
*/
* Handler for the IRC "NOTICE" 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
IRC_NOTICE(CLIENT *Client, REQUEST *Req)
{
return Send_Message(Client, Req, CLIENT_USER, false);
} /* IRC_NOTICE */
/**
* Handler for the IRC command PRIVMSG.
* Handler for the IRC "PRIVMSG" 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
IRC_PRIVMSG(CLIENT *Client, REQUEST *Req)
@@ -239,9 +194,12 @@ IRC_PRIVMSG(CLIENT *Client, REQUEST *Req)
return Send_Message(Client, Req, CLIENT_USER, true);
} /* IRC_PRIVMSG */
/**
* Handler for the IRC command SQUERY.
* Handler for the IRC "SQUERY" 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
IRC_SQUERY(CLIENT *Client, REQUEST *Req)
@@ -249,95 +207,269 @@ IRC_SQUERY(CLIENT *Client, REQUEST *Req)
return Send_Message(Client, Req, CLIENT_SERVICE, true);
} /* IRC_SQUERY */
GLOBAL bool
IRC_TRACE( CLIENT *Client, REQUEST *Req )
/*
* Handler for the IRC "TRACE" 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
IRC_TRACE(CLIENT *Client, REQUEST *Req)
{
CLIENT *from, *target, *c;
CONN_ID idx, idx2;
char user[CLIENT_USER_LEN];
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of arguments? */
if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
IRC_SetPenalty(Client, 3);
/* Search sender */
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 );
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from)
/* Search target */
if( Req->argc == 1 ) target = Client_Search( Req->argv[0] );
else target = Client_ThisServer( );
/* Forward command to other server? */
if( target != Client_ThisServer( ))
{
if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
if (target != Client_ThisServer()) {
/* Send RPL_TRACELINK back to initiator */
idx = Client_Conn( Client ); assert( idx > NONE );
idx2 = Client_Conn( Client_NextHop( target )); assert( idx2 > NONE );
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;
idx = Client_Conn(Client);
assert(idx > NONE);
idx2 = Client_Conn(Client_NextHop(target));
assert(idx2 > NONE);
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;
/* Forward command */
IRC_WriteStrClientPrefix( target, from, "TRACE %s", Req->argv[0] );
IRC_WriteStrClientPrefix(target, from, "TRACE %s", Req->argv[0]);
return CONNECTED;
}
/* Infos about all connected servers */
c = Client_First( );
while( c )
{
if( Client_Conn( c ) > NONE )
{
c = Client_First();
while (c) {
if (Client_Conn(c) > NONE) {
/* Local client */
if( Client_Type( c ) == CLIENT_SERVER )
{
if (Client_Type(c) == CLIENT_SERVER) {
/* Server link */
strlcpy( user, Client_User( c ), sizeof( user ));
if( user[0] == '~' ) 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;
strlcpy(user, Client_User(c), sizeof(user));
if (user[0] == '~')
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(( Client_Type( c ) == CLIENT_USER ) && ( strchr( Client_Modes( c ), 'o' )))
{
if (Client_Type(c) == CLIENT_USER
&& Client_HasMode(c, 'o')) {
/* IRC Operator */
if( ! IRC_WriteStrClient( from, RPL_TRACEOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
if (!IRC_WriteStrClient(from,
RPL_TRACEOPERATOR_MSG,
Client_ID(from), Client_ID(c)))
return DISCONNECTED;
}
}
c = Client_Next( c );
}
IRC_SetPenalty( Client, 3 );
return IRC_WriteStrClient( from, RPL_TRACEEND_MSG, Client_ID( from ), Conf_ServerName, PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel );
return IRC_WriteStrClient(from, RPL_TRACEEND_MSG, Client_ID(from),
Conf_ServerName, PACKAGE_NAME,
PACKAGE_VERSION, NGIRCd_DebugLevel);
} /* 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
IRC_HELP( CLIENT *Client, REQUEST *Req )
IRC_HELP(CLIENT *Client, REQUEST *Req)
{
COMMAND *cmd;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of arguments? */
if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
IRC_SetPenalty(Client, 2);
cmd = Parse_GetCommandStruct( );
while( cmd->name )
{
if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0)
|| (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) {
/* Help text available and requested */
if (Req->argc >= 1)
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++;
}
IRC_SetPenalty( Client, 2 );
return CONNECTED;
} /* 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 *
#ifdef ZLIB
Option_String(CONN_ID Idx)
@@ -346,23 +478,26 @@ Option_String(UNUSED CONN_ID Idx)
#endif
{
static char option_txt[8];
#ifdef ZLIB
UINT16 options;
options = Conn_Options(Idx);
#endif
assert(Idx != NONE);
options = Conn_Options(Idx);
strcpy(option_txt, "F"); /* No idea what this means, but the
* original ircd sends it ... */
#ifdef ZLIB
if(options & CONN_ZIP) /* zlib compression supported. */
strcat(option_txt, "z");
#ifdef SSL_SUPPORT
if(options & CONN_SSL) /* SSL encrypted link */
strlcat(option_txt, "s", sizeof(option_txt));
#endif
#ifdef ZLIB
if(options & CONN_ZIP) /* zlib compression enabled */
strlcat(option_txt, "z", sizeof(option_txt));
#endif
LogDebug(" *** %d: %d = %s", Idx, options, option_txt);
return option_txt;
} /* Option_String */
static bool
Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
{
@@ -379,19 +514,20 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
if (Req->argc == 0) {
if (!SendErrors)
return CONNECTED;
return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG,
return IRC_WriteErrClient(Client, ERR_NORECIPIENT_MSG,
Client_ID(Client), Req->command);
}
if (Req->argc == 1) {
if (!SendErrors)
return CONNECTED;
return IRC_WriteStrClient(Client, ERR_NOTEXTTOSEND_MSG,
return IRC_WriteErrClient(Client, ERR_NOTEXTTOSEND_MSG,
Client_ID(Client));
}
if (Req->argc > 2) {
if (!SendErrors)
return CONNECTED;
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
IRC_SetPenalty(Client, 2);
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
@@ -400,7 +536,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
#ifdef ICONV
@@ -495,7 +631,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
#else
if (Client_Type(cl) != ForceType) {
#endif
if (SendErrors && !IRC_WriteStrClient(
if (SendErrors && !IRC_WriteErrClient(
from, ERR_NOSUCHNICK_MSG,Client_ID(from),
currentTarget))
return DISCONNECTED;
@@ -516,7 +652,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
!Client_HasMode(from, 'o') &&
!(Client_Type(from) == CLIENT_SERVER) &&
!(Client_Type(from) == CLIENT_SERVICE)) {
if (SendErrors && !IRC_WriteStrClient(from,
if (SendErrors && !IRC_WriteErrClient(from,
ERR_NONONREG_MSG,
Client_ID(from), Client_ID(cl)))
return DISCONNECTED;
@@ -532,7 +668,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
cl2chan = Channel_NextChannelOf(cl, cl2chan);
}
if (!cl2chan) {
if (SendErrors && !IRC_WriteStrClient(
if (SendErrors && !IRC_WriteErrClient(
from, ERR_NOTONSAMECHANNEL_MSG,
Client_ID(from), Client_ID(cl)))
return DISCONNECTED;
@@ -541,7 +677,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
}
if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
&& strchr(Client_Modes(cl), 'a')) {
&& Client_HasMode(cl, 'a')) {
/* Target is away */
if (!IRC_WriteStrClient(from, RPL_AWAY_MSG,
Client_ID(from),
@@ -572,7 +708,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
} else {
if (!SendErrors)
return CONNECTED;
if (!IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
if (!IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(from), currentTarget))
return DISCONNECTED;
}
@@ -586,7 +722,6 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
return CONNECTED;
} /* Send_Message */
static bool
Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
char * message, bool SendErrors)
@@ -598,10 +733,10 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
cl = NULL;
if (strchr(Client_Modes(from), 'o') == NULL) {
if (!Client_HasMode(from, 'o')) {
if (!SendErrors)
return true;
return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
return IRC_WriteErrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from));
}
@@ -616,7 +751,7 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
{
if (!SendErrors)
return true;
return IRC_WriteStrClient(from, ERR_WILDTOPLEVEL, targetMask);
return IRC_WriteErrClient(from, ERR_WILDTOPLEVEL, targetMask);
}
/* #: hostmask, see RFC 2812, sec. 3.3.1 */
@@ -646,5 +781,4 @@ Send_Message_Mask(CLIENT * from, char * command, char * targetMask,
return CONNECTED;
} /* Send_Message_Mask */
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -28,6 +28,9 @@ GLOBAL bool IRC_SQUERY 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_KillClient PARAMS((CLIENT *Client, CLIENT *From,
const char *Nick, const char *Reason));
#endif
/* -eof- */

View File

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

View File

@@ -30,7 +30,8 @@ GLOBAL struct list_elem *Lists_GetFirst PARAMS((const struct list_head *));
GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *));
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client));
GLOBAL char *Lists_CheckReason PARAMS((struct list_head *head, CLIENT *client));
GLOBAL bool 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,
const char *mask));
@@ -41,7 +42,7 @@ GLOBAL unsigned long Lists_Count PARAMS((struct list_head *h));
GLOBAL void Lists_Free PARAMS((struct list_head *head));
GLOBAL const char *Lists_MakeMask PARAMS((const char *Pattern));
GLOBAL void Lists_MakeMask PARAMS((const char *Pattern, char *mask, size_t len));
GLOBAL const char *Lists_GetMask 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));

View File

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

View File

@@ -19,6 +19,7 @@
#include "imp.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
@@ -37,6 +38,7 @@
#include "ngircd.h"
#include "pam.h"
#include "irc-info.h"
#include "irc-mode.h"
#include "irc-write.h"
#include "exp.h"
@@ -89,13 +91,12 @@ Login_User(CLIENT * Client)
#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(Conn_Password(conn)[0] == '\0')
/* Don't do any PAM authentication at all if PAM is not
* enabled, instead emulate the behavior of the daemon
* compiled without PAM support. */
if (strcmp(Conn_Password(conn), Conf_ServerPwd) == 0)
return Login_User_PostAuth(Client);
Client_Reject(Client, "Non-empty password", false);
Client_Reject(Client, "Bad server password", false);
return DISCONNECTED;
}
@@ -109,25 +110,27 @@ Login_User(CLIENT * Client)
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);
}
if (Conf_PAM) {
/* 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 return CONNECTED;
#else
/* Check global server password ... */
if (strcmp(Conn_Password(conn), Conf_ServerPwd) != 0) {
@@ -151,6 +154,9 @@ Login_User(CLIENT * Client)
GLOBAL bool
Login_User_PostAuth(CLIENT *Client)
{
REQUEST Req;
char modes[CLIENT_MODE_LEN + 1];
assert(Client != NULL);
if (Class_HandleServerBans(Client) != CONNECTED)
@@ -185,8 +191,17 @@ Login_User_PostAuth(CLIENT *Client)
if (!IRC_Show_MOTD(Client))
return DISCONNECTED;
/* Suspend the client for a second ... */
IRC_SetPenalty(Client, 1);
/* Set default user modes */
if (Conf_DefaultUserModes[0]) {
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;
}
@@ -194,7 +209,7 @@ Login_User_PostAuth(CLIENT *Client)
#ifdef PAM
/**
* Read result of the authenticatior sub-process from pipe
* Read result of the authenticator sub-process from pipe
*
* @param r_fd File descriptor of the pipe.
* @param events (ignored IO specification)
@@ -202,6 +217,7 @@ Login_User_PostAuth(CLIENT *Client)
static void
cb_Read_Auth_Result(int r_fd, UNUSED short events)
{
char user[CLIENT_USER_LEN], *ptr;
CONN_ID conn;
CLIENT *client;
int result;
@@ -233,7 +249,14 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
}
if (result == true) {
Client_SetUser(client, Client_OrigUser(client), true);
/* Authentication succeeded, now set the correct user name
* 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);
} else
Client_Reject(client, "Bad password", false);

View File

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

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* 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
@@ -21,7 +21,7 @@
#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_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=#&+ CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=#&+:%d :are supported on this server"
#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_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"
@@ -49,6 +49,7 @@
#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_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_USERHOST_MSG "302 %s :"
@@ -56,6 +57,7 @@
#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_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_WHOISSERVER_MSG "312 %s %s %s :%s"
#define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator"

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2014 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
@@ -264,7 +264,7 @@ main(int argc, const char *argv[])
/* Initialize the "main program": chroot environment, user and
* group ID, ... */
if (!NGIRCd_Init(NGIRCd_NoDaemon)) {
Log(LOG_ALERT, "Fatal: Initialization failed");
Log(LOG_ALERT, "Fatal: Initialization failed, exiting!");
exit(1);
}
@@ -297,10 +297,10 @@ main(int argc, const char *argv[])
PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
IRCPLUSFLAGS);
#ifdef ZLIB
strcat(NGIRCd_ProtoID, "Z");
strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
#endif
if (Conf_OperCanMode)
strcat(NGIRCd_ProtoID, "o");
strlcat(NGIRCd_ProtoID, "o", sizeof NGIRCd_ProtoID);
#else /* IRCPLUS */
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
@@ -460,7 +460,7 @@ static void
Show_Version( void )
{
puts( NGIRCd_Version );
puts( "Copyright (c)2001-2013 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Copyright (c)2001-2014 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Homepage: <http://ngircd.barton.de/>\n" );
puts( "This is free software; see the source for copying conditions. There is NO" );
puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
@@ -535,21 +535,23 @@ 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 process ID!");
close(pidfd);
return;
}
if (write(pidfd, pidbuf, (size_t)len) != (ssize_t)len)
Log( LOG_ERR, "Can't write PID file (%s): %s", Conf_PidFile, strerror( errno ));
Log(LOG_ERR, "Can't write PID file (%s): %s!", Conf_PidFile,
strerror(errno));
if( close(pidfd) != 0 )
Log( LOG_ERR, "Error closing PID file (%s): %s", Conf_PidFile, strerror( errno ));
if (close(pidfd) != 0)
Log(LOG_ERR, "Error closing PID file (%s): %s!", Conf_PidFile,
strerror(errno));
} /* Pidfile_Create */
/**
* Redirect stdin, stdout and stderr to apropriate file handles.
* Redirect stdin, stdout and stderr to appropriate file handles.
*
* @param fd The file handle stdin, stdout and stderr should be redirected to.
*/
@@ -611,6 +613,13 @@ NGIRCd_getNobodyID(uid_t *uid, gid_t *gid )
#endif
#ifdef HAVE_ARC4RANDOM
static void
Random_Init(void)
{
}
#else
static bool
Random_Init_Kern(const char *file)
{
@@ -640,6 +649,7 @@ Random_Init(void)
return;
srand(rand() ^ (unsigned)getpid() ^ (unsigned)time(NULL));
}
#endif
/**
@@ -671,21 +681,22 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
}
/* SSL initialization */
if (!ConnSSL_InitLibrary())
Log(LOG_WARNING,
"Error during SSL initialization, continuing without SSL ...");
if (!ConnSSL_InitLibrary()) {
Log(LOG_ERR, "Error during SSL initialization!");
goto out;
}
/* Change root */
if (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));
goto out;
}
if (chroot(Conf_Chroot) != 0) {
Log(LOG_ERR,
"Can't change root directory to \"%s\": %s",
"Can't change root directory to \"%s\": %s!",
Conf_Chroot, strerror(errno));
goto out;
} else {
@@ -716,12 +727,19 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
if (setgid(Conf_GID) != 0) {
real_errno = errno;
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,
strerror(errno));
strerror(real_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)
goto out;
}
}
#endif
@@ -730,9 +748,9 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
if (setuid(Conf_UID) != 0) {
real_errno = errno;
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,
strerror(errno));
strerror(real_errno));
if (real_errno != EPERM)
goto out;
}
@@ -764,7 +782,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
setpgrp(0, getpid());
#endif
if (chdir("/") != 0)
Log(LOG_ERR, "Can't change directory to '/': %s",
Log(LOG_ERR, "Can't change directory to '/': %s!",
strerror(errno));
/* Detach stdin, stdout and stderr */
@@ -807,8 +825,8 @@ NGIRCd_Init(bool NGIRCd_NoDaemon)
"Changed working directory to \"%s\" ...",
pwd->pw_dir);
else
Log(LOG_INFO,
"Notice: Can't change working directory to \"%s\": %s",
Log(LOG_ERR,
"Can't change working directory to \"%s\": %s!",
pwd->pw_dir, strerror(errno));
} else
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;
CLIENT *cl;
char str[LINE_LEN], *ptr;
char str[COMMAND_LEN], *ptr;
bool njoin, xop;
/* Check features of remote server */
njoin = Conn_Options(Client_Conn(Client)) & CONN_RFC1459 ? false : true;
xop = strchr(Client_Flags(Client), 'X') ? true : false;
xop = Client_HasFlag(Client, 'X') ? true : false;
/* Get all the members of this channel */
cl2chan = Channel_FirstMember(Chan);
@@ -68,21 +68,21 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan)
strlcat(str, ",", sizeof(str));
/* Prepare user prefix (ChanOp, voiced, ...) */
if (xop && strchr(Channel_UserModes(Chan, cl), 'q'))
if (xop && Channel_UserHasMode(Chan, cl, 'q'))
strlcat(str, "~", sizeof(str));
if (xop && strchr(Channel_UserModes(Chan, cl), 'a'))
if (xop && Channel_UserHasMode(Chan, cl, 'a'))
strlcat(str, "&", sizeof(str));
if (strchr(Channel_UserModes(Chan, cl), 'o'))
if (Channel_UserHasMode(Chan, cl, 'o'))
strlcat(str, "@", sizeof(str));
if (xop && strchr(Channel_UserModes(Chan, cl), 'h'))
if (xop && Channel_UserHasMode(Chan, cl, 'h'))
strlcat(str, "%", sizeof(str));
if (strchr(Channel_UserModes(Chan, cl), 'v'))
if (Channel_UserHasMode(Chan, cl, 'v'))
strlcat(str, "+", sizeof(str));
strlcat(str, Client_ID(cl), sizeof(str));
/* Send the data if the buffer is "full" */
if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) {
if (strlen(str) > (sizeof(str) - CLIENT_NICK_LEN - 8)) {
if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED;
snprintf(str, sizeof(str), "NJOIN %s :",
@@ -150,72 +150,6 @@ Announce_Server(CLIENT * Client, CLIENT * 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
/**
@@ -298,8 +232,8 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan)
if (!*modes && !*topic)
return CONNECTED;
has_k = strchr(modes, 'k') != NULL;
has_l = strchr(modes, 'l') != NULL;
has_k = Channel_HasMode(Chan, 'k');
has_l = Channel_HasMode(Chan, 'l');
/* send CHANINFO */
if (!has_k && !has_l) {
@@ -372,7 +306,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
while (c) {
if (Client_Type(c) == CLIENT_USER ||
Client_Type(c) == CLIENT_SERVICE) {
if (!Announce_User(Client, c))
if (!Client_Announce(Client, Client_ThisServer(), c))
return DISCONNECTED;
}
c = Client_Next(c);
@@ -387,7 +321,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
}
#ifdef IRCPLUS
/* Send CHANINFO if the peer supports it */
if (strchr(Client_Flags(Client), 'C')) {
if (Client_HasFlag(Client, 'C')) {
if (!Send_CHANINFO(Client, chan))
return DISCONNECTED;
}
@@ -401,7 +335,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
}
#ifdef IRCPLUS
if (strchr(Client_Flags(Client), 'L')) {
if (Client_HasFlag(Client, 'L')) {
LogDebug("Synchronizing INVITE- and BAN-lists ...");
if (!Synchronize_Lists(Client))
return DISCONNECTED;

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* 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
@@ -46,12 +46,12 @@ Op_NoPrivileges(CLIENT * Client, REQUEST * Req)
if (from) {
Log(LOG_NOTICE, "No privileges: client \"%s\" (%s), command \"%s\"",
Req->prefix, Client_Mask(Client), Req->command);
return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
return IRC_WriteErrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from));
} else {
Log(LOG_NOTICE, "No privileges: client \"%s\", command \"%s\"",
Client_Mask(Client), Req->command);
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
return IRC_WriteErrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
}
} /* Op_NoPrivileges */
@@ -86,7 +86,7 @@ Op_Check(CLIENT * Client, REQUEST * Req)
return c;
if (!Client_HasMode(c, 'o'))
return NULL;
if (!Client_OperByMe(c) && !Conf_AllowRemoteOper)
if (Client_Conn(c) <= NONE && !Conf_AllowRemoteOper)
return NULL;
/* The client is an local IRC operator, or this server is configured

View File

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

View File

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

View File

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

View File

@@ -35,6 +35,8 @@ typedef struct _COMMAND
bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
/**< Function to handle this command */
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 bytes; /**< Number of bytes created */
} COMMAND;

View File

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

View File

@@ -242,7 +242,7 @@ ForwardLookup(const char *hostname, array *IpAddr, int af)
{
ng_ipaddr_t addr;
#ifdef HAVE_GETADDRINFO
#ifdef HAVE_WORKING_GETADDRINFO
int res;
struct addrinfo *a, *ai_results;
static struct addrinfo hints;

View File

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

View File

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

View File

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

View File

@@ -24,6 +24,8 @@
#include "exp.h"
int allow_severity = 0, deny_severity = 0;
static void Panic PARAMS (( char *Reason, int Code ));

37
src/portab/strndup.c Normal file
View File

@@ -0,0 +1,37 @@
/*
* 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

@@ -109,15 +109,16 @@ void dummy_snprintf PARAMS(( void )) { }
#define LLONG long
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
static size_t dopr PARAMS((char *buffer, size_t maxlen, const char *format,
va_list args));
static void fmtstr PARAMS((char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max));
static void fmtint PARAMS((char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags));
static void fmtfp PARAMS((char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags));
static void dopr_outch PARAMS((char *buffer, size_t *currlen, size_t maxlen,
char c));
/*
* dopr(): poor man's version of doprintf
@@ -153,7 +154,8 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args)
static size_t
dopr(char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
LLONG value;
@@ -410,8 +412,9 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
return currlen;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
static void
fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
@@ -448,8 +451,9 @@ static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
static void
fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
@@ -532,7 +536,8 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
}
}
static LDOUBLE abs_val(LDOUBLE value)
static LDOUBLE
abs_val(LDOUBLE value)
{
LDOUBLE result = value;
@@ -542,7 +547,8 @@ static LDOUBLE abs_val(LDOUBLE value)
return result;
}
static LDOUBLE POW10(int exp)
static LDOUBLE
POW10(int exp)
{
LDOUBLE result = 1;
@@ -554,7 +560,8 @@ static LDOUBLE POW10(int exp)
return result;
}
static LLONG ROUND(LDOUBLE value)
static LLONG
ROUND(LDOUBLE value)
{
LLONG intpart;
@@ -567,7 +574,8 @@ static LLONG ROUND(LDOUBLE value)
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr)
static double
my_modf(double x0, double *iptr)
{
int i;
long l;
@@ -601,8 +609,9 @@ static double my_modf(double x0, double *iptr)
}
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
static void
fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue,
int min, int max, int flags)
{
int signvalue = 0;
double ufvalue;
@@ -755,7 +764,8 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
}
}
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
static void
dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen < maxlen) {
buffer[(*currlen)] = c;
@@ -764,14 +774,25 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
}
#if !defined(HAVE_VSNPRINTF)
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
int
vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#endif
#if !defined(HAVE_SNPRINTF)
int snprintf(char *str,size_t count,const char *fmt,...)
#ifdef PROTOTYPES
int
snprintf(char *str, size_t count, const char *fmt, ...)
#else
int
snprintf(str, count, fmt, va_alist)
char *str;
size_t count;
const char *fmt;
va_dcl
#endif
{
size_t ret;
va_list ap;

View File

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

View File

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

View File

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

View File

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

View File

@@ -144,11 +144,16 @@ ngt_RandomStr(char *String, const size_t len)
assert(String != NULL);
gettimeofday(&t, NULL);
#ifndef HAVE_ARC4RANDOM
srand((unsigned)(t.tv_usec * t.tv_sec));
for (i = 0; i < len; ++i) {
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';
return String;