-- ChangeLog --
+ngIRCd
+
+ - Implemented hashed cloaked hostnames for both the "CloakHost" and
+ "CloakHostModeX" configuration options: now the admin can use the new
+ '%x' placeholder to insert a hashed version of the clients hostname,
+ and the new configuration option "CloakHostSalt" defines the salt for
+ the hash function. When "CloakHostSalt" is not set (the default), a
+ random salt will be generated after each server restart.
+
ngIRCd Release 19.2 (2012-06-19)
- doc/Capabilities.txt: document "multi-prefix" capability
-- NEWS --
+ngIRCd
+
+ - Implemented hashed cloaked hostnames for both the "CloakHost" and
+ "CloakHostModeX" configuration options: now the admin can use the new
+ '%x' placeholder to insert a hashed version of the clients hostname,
+ and the new configuration option "CloakHostSalt" defines the salt for
+ the hash function. When "CloakHostSalt" is not set (the default), a
+ random salt will be generated after each server restart.
+
ngIRCd Release 19.2 (2012-06-19)
ngIRCd 19.2~rc1 (2012-06-13)
I. Introduction
~~~~~~~~~~~~~~~
-ngIRCd is an Open Source server for the Internet Relay Chat (IRC), which
-is developed and published under the terms of the GNU General Public
-Licence, see the file COPYING for details. ngIRCd means "next generation
-IRC daemon" (which is a little bit exaggerated, "lightweight Internet Relay
-Chat server" would be better), it's written from scratch and not deduced
-from the "grandfather of IRC daemons", the daemon of the IRCNet.
+ngIRCd is a free, portable and lightweight Internet Relay Chat server for
+small or private networks, developed under the GNU General Public License
+(GPL; please see the file COPYING for details). It is simple to configure,
+can cope with dynamic IP addresses, and supports IPv6 as well as SSL. It is
+written from scratch and not based on the original IRCd.
+
+The name ngIRCd means next generation IRC daemon, which is a little bit
+exaggerated: lightweight Internet Relay Chat server most probably would be a
+better name :-)
Please see the INSTALL document for installation and upgrade information!
#
# ngIRCd -- The Next Generation IRC Daemon
-# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors
+# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE(1.6)
-AM_CONFIG_HEADER(src/config.h)
+AC_CONFIG_HEADER(src/config.h)
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
Depends: ${shlibs:Depends}, ${misc:Depends}
Provides: ircd
Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
- portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
+ from scratch and not based on the original IRCd.
.
This package contains the "standard distribution", including support for
syslog logging and compressed server-links using zlib. Please have a look
Provides: ircd
Conflicts: ngircd, ngircd-dbg
Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
- portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
+ from scratch and not based on the original IRCd.
.
In addition to the features of the "standard package", this package
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
Provides: ircd
Conflicts: ngircd, ngircd-full
Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
- portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
+ from scratch and not based on the original IRCd.
.
In addition to the features of the "standard package", this package
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CODE_SIGN_IDENTITY = "Developer ID Application: Alexander Barton";
GCC_VERSION = 4.2;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
SUBDIRS = Anope Debian MacOSX
-EXTRA_DIST = README ngircd.spec systrace.policy ngindent ngircd-bsd.sh \
- ngIRCd-Logo.gif ngircd-redhat.init platformtest.sh
+EXTRA_DIST = README \
+ ngindent \
+ ngircd-bsd.sh \
+ ngIRCd-Logo.gif \
+ ngircd-redhat.init \
+ ngircd.service \
+ ngircd.spec \
+ platformtest.sh \
+ systrace.policy
maintainer-clean-local:
rm -f Makefile Makefile.in
--- /dev/null
+[Unit]
+Description=Next Generation IRC Daemon
+After=network.target
+
+[Service]
+# don't daemonize to simplify stuff
+ExecStart=/usr/sbin/ngircd -n
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
BuildRequires: zlib-devel, openssl-devel
%description
-This package provides ngIRCd, a lightweight Internet Relay Chat
-server for small or private networks. It is simple to configure, can
-cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
-is written from scratch, not based on the original IRCd and quite
-portable.
+This package provides ngIRCd, a portable and lightweight Internet Relay
+Chat server for small or private networks, developed under the GNU
+General Public License (GPL). It is simple to configure, can cope with
+dynamic IP addresses, and supports IPv6 as well as SSL. It is written
+from scratch and not based on the original IRCd.
Advantages:
- well arranged (lean) configuration file
install-data-hook: $(static_docs) $(toplevel_docs) $(generated_docs)
$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
- if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \
- $(INSTALL) -m 600 -c sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; \
+ @if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \
+ make install-config; \
fi
$(mkinstalldirs) $(DESTDIR)$(docdir)
for f in $(static_docs) $(toplevel_docs); do \
$(INSTALL) -m 644 -c $$f $(DESTDIR)$(docdir)/; \
done
+install-config:
+ $(INSTALL) -m 600 -c sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf
+ @echo; \
+ echo " ** NOTE: Installed sample configuration file:"; \
+ echo " ** \"$(DESTDIR)$(sysconfdir)/ngircd.conf\""; \
+ echo
+
uninstall-hook:
rm -rf $(DESTDIR)$(docdir)
+ @if cmp --silent sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; then \
+ make uninstall-config; \
+ else \
+ echo; \
+ echo " ** NOTE: Not uninstalling changed configuration file:"; \
+ echo " ** \"$(DESTDIR)$(sysconfdir)/ngircd.conf\""; \
+ echo; \
+ fi
+
+uninstall-config:
+ rm -f $(DESTDIR)$(sysconfdir)/ngircd.conf
srcdoc:
make -C src srcdoc
+.PHONY: install-config uninstall-config srcdoc
+
# -eof-
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
- (c)2001-2011 Alexander Barton and Contributors.
+ (c)2001-2012 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
mode since description
a 0.3.0 User is away.
+ B 20 User is flagged as a "bot".
c 17 IRC operator wants to receive connect/disconnect NOTICEs.
C 19 Only users that share a channel are allowed to send messages.
i 0.0.1 User is "invisible".
k 0.6.0 Channel has a "key" (a password).
l 0.6.0 Channel has a user limit.
m 0.3.0 Channel is moderated, only "voiced" users can send messages.
+ M 20 Only registered users (and IRC Ops) can send messages.
n 0.3.0 Channel doesn't allow messages of users not being members.
O 18 Only IRC operators are allowed to join this channel.
P 0.5.0 Channel is "persistent".
# Connect to the remote server using TLS/SSL (Default: false)
;SSLConnect = yes
- # Define a (case insensitive) mask matching nick names that should be
- # treated as IRC services when introduced via this remote server.
+ # Define a (case insensitive) list of masks matching nick names that
+ # should be treated as IRC services when introduced via this remote
+ # server, separated by commas (",").
# REGULAR SERVERS DON'T NEED this parameter, so leave it empty
# (which is the default).
# When you are connecting IRC services which mask as a IRC server
# and which use "virtual users" to communicate with, for example
# "NickServ" and "ChanServ", you should set this parameter to
- # something like "*Serv".
- ;ServiceMask = *Serv
+ # something like "*Serv" or "NickServ,ChanServ,XyzServ".
+ ;ServiceMask = *Serv,Global
[Server]
# More [Server] sections, if you like ...
Connect to the remote server using TLS/SSL. Default: false.
.TP
\fBServiceMask\fR (string)
-Define a (case insensitive) mask matching nick names that should be treated as
-IRC services when introduced via this remote server. REGULAR SERVERS DON'T NEED
-this parameter, so leave it empty (which is the default).
+Define a (case insensitive) list of masks matching nick names that should be
+treated as IRC services when introduced via this remote server, separated
+by commas (","). REGULAR SERVERS DON'T NEED this parameter, so leave it empty
+(which is the default).
.PP
.RS
When you are connecting IRC services which mask as a IRC server and which use
"virtual users" to communicate with, for example "NickServ" and "ChanServ",
-you should set this parameter to something like "*Serv".
+you should set this parameter to something like "*Serv", "*Serv,OtherNick",
+or "NickServ,ChanServ,XyzServ".
.SH [CHANNEL]
Pre-defined channels can be configured in
.I [Channel]
GLOBAL void
Channel_Init( void )
{
- CHANNEL *sc;
-
My_Channels = NULL;
My_Cl2Chan = NULL;
-
- sc = Channel_Create("&SERVER");
- if (sc) {
- Channel_SetModes(sc, "mnPt");
- Channel_SetTopic(sc, Client_ThisServer(), "Server Messages");
- }
} /* Channel_Init */
}
+/**
+ * Generate predefined persistent channels and &SERVER
+ */
GLOBAL void
Channel_InitPredefined( void )
{
- /* Generate predefined persistent channels */
-
CHANNEL *new_chan;
const struct Conf_Channel *conf_chan;
const char *c;
}
if (channel_count)
array_free(&Conf_Channels);
+
+ /* Make sure the local &SERVER channel exists */
+ if (!Channel_Search("&SERVER")) {
+ new_chan = Channel_Create("&SERVER");
+ if (new_chan) {
+ Channel_SetModes(new_chan, "mnPt");
+ Channel_SetTopic(new_chan, Client_ThisServer(),
+ "Server Messages");
+ } else
+ Log(LOG_ERR, "Failed to create \"&SERVER\" channel!");
+ } else
+ LogDebug("Required channel \"&SERVER\" already exists, ok.");
} /* Channel_InitPredefined */
if (strchr(Channel_Modes(Chan), 'n') && !is_member)
return false;
+ if (strchr(Channel_Modes(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;
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
} /* Client_SetFlags */
-GLOBAL void
-Client_SetPassword( CLIENT *Client, const char *Pwd )
-{
- /* set password sent by client */
-
- assert( Client != NULL );
- assert( Pwd != NULL );
-
- strlcpy(Client->pwd, Pwd, sizeof(Client->pwd));
-} /* Client_SetPassword */
-
-
GLOBAL void
Client_SetAway( CLIENT *Client, const char *Txt )
{
/**
* Get potentially cloaked hostname of a client.
+ *
* 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
*/
GLOBAL char *
Client_HostnameCloaked(CLIENT *Client)
{
+ static char Cloak_Buffer[CLIENT_HOST_LEN];
+
assert(Client != NULL);
- if (Client_HasMode(Client, 'x'))
- return Client_ID(Client->introducer);
- else
+
+ if (!Client_HasMode(Client, 'x'))
return Client_Hostname(Client);
-} /* Client_HostnameCloaked */
+ /* Do simple mapping to the server ID? */
+ if (!*Conf_CloakHostModeX)
+ return Client_ID(Client->introducer);
-GLOBAL char *
-Client_Password( CLIENT *Client )
-{
- assert( Client != NULL );
- return Client->pwd;
-} /* Client_Password */
+ strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
+ strlcat(Cloak_Buffer, Conf_CloakHostSalt, CLIENT_HOST_LEN);
+
+ snprintf(Cloak_Buffer, CLIENT_HOST_LEN, Conf_CloakHostModeX,
+ Hash(Cloak_Buffer));
+
+ return Cloak_Buffer;
+} /* Client_HostnameCloaked */
GLOBAL char *
/**
* Return ID of a client with cloaked hostname: "client!user@server-name"
+ *
* This client ID is used for IRC prefixes, for example.
* Please note that this function uses a global static buffer, so you can't
* nest invocations without overwriting earlier results!
* If the client has not enabled cloaking, the real hostname is used.
+ *
* @param Client Pointer to client structure
* @return Pointer to global buffer containing the client ID
*/
Client_MaskCloaked(CLIENT *Client)
{
static char Mask_Buffer[GETID_LEN];
- char Cloak_Buffer[GETID_LEN];
assert (Client != NULL);
if (!Client_HasMode(Client, 'x'))
return Client_Mask(Client);
- if(*Conf_CloakHostModeX) {
- strlcpy(Cloak_Buffer, Client->host, GETID_LEN);
- strlcat(Cloak_Buffer, Conf_CloakHostSalt, GETID_LEN);
- snprintf(Cloak_Buffer, GETID_LEN, Conf_CloakHostModeX, Hash(Cloak_Buffer));
- } else {
- strncpy(Cloak_Buffer, Client_ID(Client->introducer), GETID_LEN);
- }
-
- snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
- Client->id, Client->user, Cloak_Buffer);
+ snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user,
+ Client_HostnameCloaked(Client));
return Mask_Buffer;
} /* Client_MaskCloaked */
return false;
}
+ if (Client_Type(Client) != CLIENT_SERVER
+ && Client_Type(Client) != CLIENT_SERVICE) {
+ /* Make sure that this isn't a restricted/forbidden nick name */
+ if (Conf_NickIsBlocked(Nick)) {
+ IRC_WriteStrClient(Client, ERR_FORBIDDENNICKNAME_MSG,
+ Client_ID(Client), Nick);
+ return false;
+ }
+ }
+
/* Nickname already registered? */
if (Client_Search(Nick)) {
IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
Client_SetType(Client, Type);
if (From) {
- if (Conf_IsService(Conf_GetServer(Client_Conn(From)),
+ if (Conf_NickIsService(Conf_GetServer(Client_Conn(From)),
Client_ID(Client)))
Client_SetType(Client, CLIENT_SERVICE);
LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).",
CONN_ID conn_id; /* ID of the connection (if local) or NONE (remote) */
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 pwd[CLIENT_PASS_LEN]; /* password received of the client */
char host[CLIENT_HOST_LEN]; /* hostname of the client */
char user[CLIENT_USER_LEN]; /* user name ("login") */
#if defined(PAM) && defined(IDENTAUTH)
#endif
GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client ));
GLOBAL char *Client_HostnameCloaked PARAMS(( CLIENT *Client ));
-GLOBAL char *Client_Password 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 void Client_SetUser PARAMS(( CLIENT *Client, const char *User, bool Idented ));
GLOBAL void Client_SetOrigUser PARAMS(( CLIENT *Client, const char *User ));
GLOBAL void Client_SetInfo PARAMS(( CLIENT *Client, const char *Info ));
-GLOBAL void Client_SetPassword PARAMS(( CLIENT *Client, const char *Pwd ));
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 ));
puts("[LIMITS]");
printf(" ConnectRetry = %d\n", Conf_ConnectRetry);
- printf(" MaxConnections = %ld\n", Conf_MaxConnections);
+ printf(" MaxConnections = %d\n", Conf_MaxConnections);
printf(" MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
}
/**
- * Check if the given nick name is an service.
+ * Check if the given nick name is reserved for services on a particular server.
*
+ * @param ConfServer The server index to check.
+ * @param Nick The nick name to check.
* @returns true if the given nick name belongs to an "IRC service".
*/
GLOBAL bool
-Conf_IsService(int ConfServer, const char *Nick)
+Conf_NickIsService(int ConfServer, const char *Nick)
{
- return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick);
+ assert (ConfServer >= 0);
+ assert (ConfServer < MAX_SERVERS);
+
+ return MatchCaseInsensitiveList(Conf_Server[ConfServer].svs_mask,
+ Nick, ",");
+}
+
+/**
+ * Check if the given nick name is blocked for "normal client" use.
+ *
+ * @param ConfServer The server index or NONE to check all configured servers.
+ * @param Nick The nick name to check.
+ * @returns true if the given nick name belongs to an "IRC service".
+ */
+GLOBAL bool
+Conf_NickIsBlocked(const char *Nick)
+{
+ int i;
+
+ for(i = 0; i < MAX_SERVERS; i++) {
+ if (!Conf_Server[i].name[0])
+ continue;
+ if (Conf_NickIsService(i, Nick))
+ return true;
+ }
+ return false;
}
/**
Set_Defaults(bool InitServers)
{
int i;
- char random[RANDOM_SALT_LEN];
+ char random[RANDOM_SALT_LEN + 1];
/* Global */
strcpy(Conf_ServerName, "");
return;
}
if (strcasecmp(Var, "MaxConnections") == 0) {
- Conf_MaxConnections = atol(Arg);
+ Conf_MaxConnections = atoi(Arg);
if (!Conf_MaxConnections && strcmp(Arg, "0"))
Config_Error_NaN(Line, Var);
return;
bool config_valid = true;
char *ptr;
+ /* Emit a warning when the config file is not a full path name */
+ if (NGIRCd_ConfFile[0] && NGIRCd_ConfFile[0] != '/') {
+ Config_Error(LOG_WARNING,
+ "Not specifying a full path name to \"%s\" can cause problems when rehashing the server!",
+ NGIRCd_ConfFile);
+ }
+
/* Validate configured server name, see RFC 2812 section 2.3.1 */
ptr = Conf_ServerName;
do {
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
GLOBAL bool Conf_ConnectIPv4;
/** Maximum number of simultaneous connections to this server */
-GLOBAL long Conf_MaxConnections;
+GLOBAL int Conf_MaxConnections;
/** Maximum number of channels a user can join */
GLOBAL int Conf_MaxJoins;
GLOBAL bool Conf_DisableServer PARAMS(( const char *Name ));
GLOBAL bool Conf_AddServer PARAMS(( const char *Name, UINT16 Port, const char *Host, const char *MyPwd, const char *PeerPwd ));
-GLOBAL bool Conf_IsService PARAMS((int ConfServer, const char *Nick));
+GLOBAL bool Conf_NickIsService PARAMS((int ConfServer, const char *Nick));
+GLOBAL bool Conf_NickIsBlocked PARAMS((const char *Nick));
/* Password required by WEBIRC command */
GLOBAL char Conf_WebircPwd[CLIENT_PASS_LEN];
#endif /* _GNUTLS */
Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
ConnSSL_LogCertInfo(c);
+
+ Conn_StartLogin(CONNECTION2ID(c));
return 1;
}
static bool Handle_Write PARAMS(( CONN_ID Idx ));
static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
-static int New_Connection PARAMS(( int Sock ));
+static int New_Connection PARAMS(( int Sock, bool IsSSL ));
static CONN_ID Socket2Index PARAMS(( int Sock ));
static void Read_Request PARAMS(( CONN_ID Idx ));
static unsigned int Handle_Buffer PARAMS(( CONN_ID Idx ));
cb_listen(int sock, short irrelevant)
{
(void) irrelevant;
- (void) New_Connection(sock);
+ (void) New_Connection(sock, false);
}
int fd;
(void) irrelevant;
- fd = New_Connection(sock);
+ fd = New_Connection(sock, true);
if (fd < 0)
return;
io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl);
return ok;
} /* Conn_WriteStr */
+GLOBAL char*
+Conn_Password( CONN_ID Idx )
+{
+ assert( Idx > NONE );
+ if (My_Connections[Idx].pwd == NULL)
+ return (char*)"\0";
+ else
+ return My_Connections[Idx].pwd;
+} /* Conn_Password */
+
+GLOBAL void
+Conn_SetPassword( CONN_ID Idx, const char *Pwd )
+{
+ assert( Idx > NONE );
+
+ if (My_Connections[Idx].pwd)
+ free(My_Connections[Idx].pwd);
+
+ My_Connections[Idx].pwd = strdup(Pwd);
+ if (My_Connections[Idx].pwd == NULL) {
+ Log(LOG_EMERG, "Can't allocate memory! [Conn_SetPassword]");
+ exit(1);
+ }
+} /* Conn_SetPassword */
/**
* Append Data to the outbound write buffer of a connection.
array_free(&My_Connections[Idx].rbuf);
array_free(&My_Connections[Idx].wbuf);
+ if (My_Connections[Idx].pwd != NULL)
+ free(My_Connections[Idx].pwd);
/* Clean up connection structure (=free it) */
Init_Conn_Struct( Idx );
* Initialize new client connection on a listening socket.
*
* @param Sock Listening socket descriptor.
+ * @param IsSSL true if this socket expects SSL-encrypted data.
* @returns Accepted socket descriptor or -1 on error.
*/
static int
-New_Connection(int Sock)
+New_Connection(int Sock, bool IsSSL)
{
#ifdef TCPWRAP
struct request_info req;
#endif
ng_ipaddr_t new_addr;
char ip_str[NG_INET_ADDRSTRLEN];
- int new_sock, new_sock_len, identsock;
+ int new_sock, new_sock_len;
CLIENT *c;
long cnt;
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();
+
+#ifdef SSL_SUPPORT
+ /* Delay connection initalization until SSL handshake is finished */
+ if (!IsSSL)
+#endif
+ Conn_StartLogin(new_sock);
+
+ return new_sock;
+} /* New_Connection */
+
+
+/**
+ * Finish connection initialization, start resolver subprocess.
+ *
+ * @param Idx Connection index.
+ */
+GLOBAL void
+Conn_StartLogin(CONN_ID Idx)
+{
+ int ident_sock = -1;
+
+ assert(Idx >= 0);
+
+ /* Nothing to do if DNS (and resolver subprocess) is disabled */
+ if (!Conf_DNS)
+ return;
- identsock = new_sock;
#ifdef IDENTAUTH
- if (!Conf_Ident)
- identsock = -1;
+ /* Should we make an IDENT request? */
+ if (Conf_Ident)
+ ident_sock = My_Connections[Idx].sock;
#endif
- if (Conf_DNS) {
- if (Conf_NoticeAuth) {
+
+ if (Conf_NoticeAuth) {
+ /* Send "NOTICE AUTH" messages to the client */
#ifdef IDENTAUTH
- if (Conf_Ident)
- (void)Conn_WriteStr(new_sock,
- "NOTICE AUTH :*** Looking up your hostname and checking ident");
- else
+ if (Conf_Ident)
+ (void)Conn_WriteStr(Idx,
+ "NOTICE AUTH :*** Looking up your hostname and checking ident");
+ else
#endif
- (void)Conn_WriteStr(new_sock,
- "NOTICE AUTH :*** Looking up your hostname");
- }
- Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
- identsock, cb_Read_Resolver_Result);
+ (void)Conn_WriteStr(Idx,
+ "NOTICE AUTH :*** Looking up your hostname");
+ (void)Handle_Write(Idx);
}
- Account_Connection();
- return new_sock;
-} /* New_Connection */
+ Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr,
+ ident_sock, cb_Read_Resolver_Result);
+}
/**
if (My_Connections[i].lastping <
time(NULL) - Conf_PongTimeout) {
/* Timeout */
- LogDebug
- ("Connection %d: Ping timeout: %d seconds.",
- i, Conf_PongTimeout);
- snprintf(msg, sizeof(msg), "Ping timeout: %d seconds", Conf_PongTimeout);
+ snprintf(msg, sizeof(msg),
+ "Ping timeout: %d seconds",
+ Conf_PongTimeout);
+ LogDebug("Connection %d: %s.", i, msg);
Conn_Close(i, NULL, msg, true);
}
} else if (My_Connections[i].lastdata <
Client_SetHostname(c, readbuf);
if (Conf_NoticeAuth)
(void)Conn_WriteStr(i,
- "NOTICE AUTH :*** Found your hostname");
+ "NOTICE AUTH :*** Found your hostname: %s",
+ My_Connections[i].host);
#ifdef IDENTAUTH
++identptr;
if (*identptr) {
}
if (Conf_NoticeAuth) {
(void)Conn_WriteStr(i,
- "NOTICE AUTH :*** Got %sident response",
- *ptr ? "invalid " : "");
+ "NOTICE AUTH :*** Got %sident response%s%s",
+ *ptr ? "invalid " : "",
+ *ptr ? "" : ": ",
+ *ptr ? "" : identptr);
}
} else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
"NOTICE AUTH :*** No ident response");
}
#endif
+
+ if (Conf_NoticeAuth)
+ (void)Handle_Write(i);
+
Class_HandleServerBans(c);
}
#ifdef DEBUG
#define CONN_SSL_WANT_READ 128 /* SSL/TLS library needs to read protocol data */
#define CONN_SSL_FLAGS_ALL (CONN_SSL_CONNECT|CONN_SSL|CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ)
#endif
-typedef long CONN_ID;
+typedef int CONN_ID;
#include "client.h"
#include "proc.h"
ng_ipaddr_t addr; /* Client address */
PROC_STAT proc_stat; /* Status of resolver process */
char host[HOST_LEN]; /* Hostname */
+ char *pwd; /* password received of the client */
array rbuf; /* Read buffer */
array wbuf; /* Write buffer */
time_t signon; /* Signon ("connect") time */
GLOBAL CONN_ID Pool_Size;
GLOBAL long WCounter;
+#define CONNECTION2ID(x) (long)(x - My_Connections)
+
#endif /* CONN_MODULE */
GLOBAL unsigned int Conn_InitListeners PARAMS(( void ));
GLOBAL void Conn_ExitListeners PARAMS(( void ));
+GLOBAL void Conn_StartLogin PARAMS((CONN_ID Idx));
+
GLOBAL void Conn_Handler PARAMS(( void ));
GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, const char *Format, ... ));
+GLOBAL char* Conn_Password PARAMS(( CONN_ID Idx ));
+GLOBAL void Conn_SetPassword PARAMS(( CONN_ID Idx, const char *Pwd ));
+
GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient ));
GLOBAL void Conn_SyncServerStruct PARAMS(( void ));
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));
+
#ifdef SSL_SUPPORT
GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
#endif
/** Supported user modes. */
-#define USERMODES "acCiorRswx"
+#define USERMODES "aBcCiorRswx"
/** Supported channel modes. */
-#define CHANMODES "abehiIklmnoOPqrRstvz"
+#define CHANMODES "abehiIklmMnoOPqrRstvz"
/** Away message for users connected to linked servers. */
#define DEFAULT_AWAY_MSG "Away"
static int io_dispatch_kqueue(struct timeval *tv);
static bool io_event_change_kqueue(int, short, const int action);
+
+#ifndef EV_SET
+/* Taken from /usr/include/sys/event.h of FreeBSD 8.1 and required by all
+ * platforms that have kqueue but lack EV_SET() -- for example FreeBSD 4. */
+#define EV_SET(kevp, a, b, c, d, e, f) do { \
+ struct kevent *__kevp__ = (kevp); \
+ __kevp__->ident = (a); \
+ __kevp__->filter = (b); \
+ __kevp__->flags = (c); \
+ __kevp__->fflags = (d); \
+ __kevp__->data = (e); \
+ __kevp__->udata = (f); \
+} while(0)
+#endif
#endif
#ifdef IO_USE_POLL
* @param Capabilities Capability flags (bitmask).
* @return Pointer to textual representation.
*/
-char
-*Get_CAP_String(int Capabilities)
+char *
+Get_CAP_String(int Capabilities)
{
static char txt[COMMAND_LEN];
assert( Client != NULL );
assert( Chan != NULL );
+ IRC_SetPenalty(Client, 1);
+
is_member = Channel_IsMemberOf(Chan, Client);
/* Secret channel? */
is_visible = strchr(client_modes, 'i') == NULL;
if (is_member || is_visible) {
- if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
- break;
-
strcpy(flags, who_flags_status(client_modes));
if (is_ircop)
strlcat(flags, "*", sizeof(flags));
count++;
}
}
+
+ /* If there are a lot of clients, augment penalty a bit */
+ if (count > MAX_RPL_WHO)
+ IRC_SetPenalty(Client, 1);
+
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
Channel_Name(Chan));
}
if (Mask)
ngt_LowerStr(Mask);
+ IRC_SetPenalty(Client, 3);
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_USER)
continue;
chan = Channel_Search(Req->argv[0]);
if (chan) {
/* Members of a channel have been requested */
- IRC_SetPenalty(Client, 1);
return IRC_WHO_Channel(Client, chan, only_ops);
}
if (strcmp(Req->argv[0], "0") != 0) {
/* A mask has been given. But please note this RFC
* stupidity: "0" is same as no arguments ... */
- IRC_SetPenalty(Client, 3);
return IRC_WHO_Mask(Client, Req->argv[0], only_ops);
}
}
Client_ID(from), Client_ID(c)))
return DISCONNECTED;
+ /* IRC-Bot? */
+ if (Client_HasMode(c, 'B') &&
+ !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG,
+ Client_ID(from), Client_ID(c)))
+ return DISCONNECTED;
+
/* Connected using SSL? */
if (Conn_UsesSSL(Client_Conn(c)) &&
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
static bool
Show_MOTD_End(CLIENT *Client)
{
- return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
+ if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client)))
+ return DISCONNECTED;
+
+ if (*Conf_CloakHost)
+ return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+ Client_ID(Client),
+ Client_Hostname(Client));
+
+ return CONNECTED;
}
#ifdef SSL_SUPPORT
Client_ID(Client));
}
- Client_SetPassword(Client, Req->argv[0]);
+ Conn_SetPassword(Client_Conn(Client), Req->argv[0]);
/* Protocol version */
if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) {
{
char the_modes[COMMAND_LEN], x[2], *mode_ptr;
bool ok, set;
+ bool send_RPL_HOSTHIDDEN_MSG = false;
int mode_arg;
size_t len;
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
break;
+ case 'B': /* Bot */
+ if (Client_HasMode(Client, 'r'))
+ ok = IRC_WriteStrClient(Origin,
+ ERR_RESTRICTED_MSG,
+ Client_ID(Origin));
+ else
+ x[0] = 'B';
+ break;
case 'c': /* Receive connect notices
* (only settable by IRC operators!) */
if (!set || Client_Type(Client) == CLIENT_SERVER
ERR_RESTRICTED_MSG,
Client_ID(Origin));
break;
+ case 'R': /* Registered (not [un]settable by clients) */
+ if (Client_Type(Client) == CLIENT_SERVER)
+ x[0] = 'R';
+ else
+ ok = IRC_WriteStrClient(Origin,
+ ERR_NICKREGISTER_MSG,
+ Client_ID(Origin));
+ break;
case 'x': /* Cloak hostname */
if (Client_HasMode(Client, 'r'))
ok = IRC_WriteStrClient(Origin,
Client_ID(Origin));
else
x[0] = 'x';
+ send_RPL_HOSTHIDDEN_MSG = true;
break;
default:
if (Client_Type(Client) != CLIENT_SERVER) {
"MODE %s :%s",
Client_ID(Target),
the_modes);
+ if (send_RPL_HOSTHIDDEN_MSG)
+ IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+ Client_ID(Client),
+ Client_HostnameCloaked(Client));
}
LogDebug("%s \"%s\": Mode change, now \"%s\".",
Client_TypeText(Target), Client_Mask(Target),
goto chan_exit;
}
case 'i': /* Invite only */
+ case 'M': /* Only identified nicks can write */
case 'm': /* Moderated */
case 'n': /* Only members can write */
case 't': /* Topic locked */
Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", true);
return DISCONNECTED;
}
- if( strcmp( Client_Password( Client ), Conf_Server[i].pwd_in ) != 0 )
+ if( strcmp( Conn_Password( Client_Conn( Client ) ),
+ Conf_Server[i].pwd_in ) != 0 )
{
/* wrong password */
Log( LOG_ERR, "Connection %d: Got bad password from server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
static char *
-Option_String( CONN_ID Idx )
+#ifdef ZLIB
+Option_String(CONN_ID Idx)
+#else
+Option_String(UNUSED CONN_ID Idx)
+#endif
{
static char option_txt[8];
+#ifdef ZLIB
UINT16 options;
options = Conn_Options(Idx);
+#endif
strcpy(option_txt, "F"); /* No idea what this means, but the
* original ircd sends it ... */
* the beahiour of the daemon compiled without PAM support:
* because there can't be any "server password", all
* passwords supplied are classified as "wrong". */
- if(Client_Password(Client)[0] == '\0')
+ if(Conn_Password(conn)[0] == '\0')
return Login_User_PostAuth(Client);
Client_Reject(Client, "Non-empty password", false);
return DISCONNECTED;
}
- if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) {
+ if (Conf_PAMIsOptional &&
+ strcmp(Conn_Password(conn), "") == 0) {
/* Clients are not required to send a password and to be PAM-
* authenticated at all. If not, they won't become "identified"
* and keep the "~" in their supplied user name.
}
#else
/* Check global server password ... */
- if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
+ if (strcmp(Conn_Password(conn), Conf_ServerPwd) != 0) {
/* Bad password! */
Client_Reject(Client, "Bad server password", false);
return DISCONNECTED;
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/**
* Match string with pattern.
*
- * @param Pattern Pattern to match with
- * @param String Input string
- * @return true if pattern matches
+ * @param Pattern Pattern to match with
+ * @param String Input string
+ * @return true if pattern matches
*/
GLOBAL bool
Match( const char *Pattern, const char *String )
/**
* Match string with pattern case-insensitive.
*
- * @param pattern Pattern to match with
- * @param searchme Input string, at most COMMAND_LEN-1 characters long
- * @return true if pattern matches
+ * @param Pattern Pattern to match with
+ * @param String Input string, at most COMMAND_LEN-1 characters long
+ * @return true if pattern matches
*/
GLOBAL bool
-MatchCaseInsensitive(const char *pattern, const char *searchme)
+MatchCaseInsensitive(const char *Pattern, const char *String)
{
char haystack[COMMAND_LEN];
- strlcpy(haystack, searchme, sizeof(haystack));
- return Match(pattern, ngt_LowerStr(haystack));
+ strlcpy(haystack, String, sizeof(haystack));
+ return Match(Pattern, ngt_LowerStr(haystack));
+} /* MatchCaseInsensitive */
+
+
+/**
+ * Match string with pattern case-insensitive.
+ *
+ * @param pattern Pattern to match with
+ * @param String Input string, at most COMMAND_LEN-1 characters long
+ * @param Separator Character separating the individual patterns in the list
+ * @return true if pattern matches
+ */
+GLOBAL bool
+MatchCaseInsensitiveList(const char *Pattern, const char *String,
+ const char *Separator)
+{
+ char tmp_pattern[COMMAND_LEN], haystack[COMMAND_LEN], *ptr;
+
+ strlcpy(tmp_pattern, Pattern, sizeof(tmp_pattern));
+ strlcpy(haystack, String, sizeof(haystack));
+ ngt_LowerStr(haystack);
+
+ ptr = strtok(tmp_pattern, Separator);
+ while (ptr) {
+ ngt_TrimStr(ptr);
+ if (Match(ptr, haystack))
+ return true;
+ ptr = strtok(NULL, Separator);
+ }
+ return false;
} /* MatchCaseInsensitive */
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Wildcard pattern matching (header)
*/
-GLOBAL bool Match PARAMS(( const char *Pattern, const char *String ));
-GLOBAL bool MatchCaseInsensitive PARAMS(( const char *Pattern, const char *searchme ));
+GLOBAL bool Match PARAMS((const char *Pattern, const char *String));
+
+GLOBAL bool MatchCaseInsensitive PARAMS((const char *Pattern,
+ const char *String));
+
+GLOBAL bool MatchCaseInsensitiveList PARAMS((const char *Pattern,
+ const char *String,
+ const char *Separator));
#endif
#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 CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
+#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
#define RPL_NOTOPIC_MSG "331 %s %s :No topic is set"
#define RPL_TOPIC_MSG "332 %s %s :%s"
#define RPL_TOPICSETBY_MSG "333 %s %s %s %u"
+#define RPL_WHOISBOT_MSG "335 %s %s :is a IRC Bot"
#define RPL_INVITING_MSG "341 %s %s %s%s"
#define RPL_INVITELIST_MSG "346 %s %s %s"
#define RPL_ENDOFINVITELIST_MSG "347 %s %s :End of channel invite list"
#define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator"
#define RPL_YOURESERVICE_MSG "383 %s :You are service %s"
#define RPL_TIME_MSG "391 %s %s :%s"
+#define RPL_HOSTHIDDEN_MSG "396 %s %s :is your displayed hostname now"
#define ERR_NOSUCHNICK_MSG "401 %s %s :No such nick or channel name"
#define ERR_NOSUCHSERVER_MSG "402 %s %s :No such server"
#define ERR_NOSUCHCHANNEL_MSG "403 %s %s :No such channel"
-#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel"
+#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel (+m) -- Moderated"
#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels"
#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname"
#define ERR_NOORIGIN_MSG "409 %s :No origin specified"
#define ERR_NONICKNAMEGIVEN_MSG "431 %s :No nickname given"
#define ERR_ERRONEUSNICKNAME_MSG "432 %s %s :Erroneous nickname"
#define ERR_NICKNAMETOOLONG_MSG "432 %s %s :Nickname too long, max. %u characters"
+#define ERR_FORBIDDENNICKNAME_MSG "432 %s %s :Nickname is forbidden/blocked"
#define ERR_NICKNAMEINUSE_MSG "433 %s %s :Nickname already in use"
#define ERR_USERNOTINCHANNEL_MSG "441 %s %s %s :They aren't on that channel"
#define ERR_NOTONCHANNEL_MSG "442 %s %s :You are not on that channel"
#define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error"
#define ERR_ALREADYREGISTRED_MSG "462 %s :Connection already registered"
#define ERR_PASSWDMISMATCH_MSG "464 %s :Invalid password"
-#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)"
-#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z)"
-#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O)"
-#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R)"
+#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l) -- Channel is too full, try later"
+#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z) -- SSL connections only"
+#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O) -- IRC opers only"
+#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R) -- Registered users only"
#define ERR_UNKNOWNMODE_MSG "472 %s %c :is unknown mode char for %s"
-#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)"
-#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)"
-#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k)"
+#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i) -- Invited users only"
+#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b) -- You are banned"
+#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k) -- Wrong channel key"
#define ERR_NOCHANMODES_MSG "477 %s %s :Channel doesn't support modes"
#define ERR_LISTFULL_MSG "478 %s %s %s: Channel list is full (%d)"
#define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied"
#define ERR_CHANOPPRIVTOLOW_MSG "482 %s %s :Your privileges are to low"
#define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!"
#define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted"
+#define ERR_NICKREGISTER_MSG "484 %s :Cannot modify user mode (+R) -- Use IRC services"
#define ERR_NOOPERHOST_MSG "491 %s :Not configured for your host"
#define ERR_NOTONSAMECHANNEL_MSG "493 %s :You must share a common channel with %s"
/* Set supplied client password */
if (password)
free(password);
- password = strdup(Client_Password(Client));
- conv.appdata_ptr = Client_Password(Client);
+ password = strdup(Conn_Password(Client_Conn(Client)));
+ conv.appdata_ptr = Conn_Password(Client_Conn(Client));
/* Initialize PAM */
retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam);
* Fill a String with random chars
*/
GLOBAL char *
-ngt_RandomStr( char *String, const size_t len)
+ngt_RandomStr(char *String, const size_t len)
{
- assert(String != NULL);
+ static const char chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\"#$&'()*+,-./:;<=>?@[\\]^_`";
+ struct timeval t;
+ size_t i;
- static const char chars[] =
- "0123456789ABCDEFGHIJKLMNO"
- "PQRSTUVWXYZabcdefghijklmn"
- "opqrstuvwxyz!\"#$&'()*+,-"
- "./:;<=>?@[\\]^_`";
+ assert(String != NULL);
- struct timeval t;
gettimeofday(&t, NULL);
- srand(t.tv_usec * t.tv_sec);
+ srand((unsigned)(t.tv_usec * t.tv_sec));
- for (size_t i = 0; i < len; ++i) {
+ for (i = 0; i < len; ++i) {
String[i] = chars[rand() % (sizeof(chars) - 1)];
}
-
String[len] = '\0';
return String;