#include "portab.h"
-static char UNUSED id[] = "$Id: conf.c,v 1.105 2008/03/18 20:12:47 fw Exp $";
-
#include "imp.h"
#include <assert.h>
#include <errno.h>
#include "client.h"
#include "defines.h"
#include "log.h"
+#include "match.h"
#include "resolve.h"
#include "tool.h"
static void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool ngircd_starting ));
-static void Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
+static bool Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
static void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
+#ifdef WANT_IPV6
+#define DEFAULT_LISTEN_ADDRSTR "::,0.0.0.0"
+#else
+#define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
+#endif
+
+#ifdef SSL_SUPPORT
+struct SSLOptions Conf_SSLOptions;
+
+static void
+ConfSSL_Init(void)
+{
+ free(Conf_SSLOptions.KeyFile);
+ Conf_SSLOptions.KeyFile = NULL;
+
+ free(Conf_SSLOptions.CertFile);
+ Conf_SSLOptions.CertFile = NULL;
+
+ free(Conf_SSLOptions.DHFile);
+ Conf_SSLOptions.DHFile = NULL;
+ array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
+}
+
+
+static void
+ConfSSL_Puts(void)
+{
+ if (Conf_SSLOptions.KeyFile)
+ printf( " SSLKeyFile = %s\n", Conf_SSLOptions.KeyFile);
+ if (Conf_SSLOptions.CertFile)
+ printf( " SSLCertFile = %s\n", Conf_SSLOptions.CertFile);
+ if (Conf_SSLOptions.DHFile)
+ printf( " SSLDHFile = %s\n", Conf_SSLOptions.DHFile);
+ if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
+ puts(" SSLKeyFilePassword = <secret>" );
+ array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
+}
+#endif
static char *
strdup_warn(const char *str)
struct group *grp;
unsigned int i;
char *topic;
+ bool config_valid;
Use_Log = false;
- Read_Config( true );
- Validate_Config(true, false);
+ if (! Read_Config(true))
+ return 1;
+
+ config_valid = Validate_Config(true, false);
/* If stdin and stdout ("you can read our nice message and we can
* read in your keypress") are valid tty's, wait for a key: */
printf( " MotdPhrase = %s\n", Conf_MotdPhrase );
printf( " ChrootDir = %s\n", Conf_Chroot );
printf( " PidFile = %s\n", Conf_PidFile);
+ printf(" Listen = %s\n", Conf_ListenAddress);
fputs(" Ports = ", stdout);
ports_puts(&Conf_ListenPorts);
+#ifdef SSL_SUPPORT
+ fputs(" SSLPorts = ", stdout);
+ ports_puts(&Conf_SSLOptions.ListenPorts);
+ ConfSSL_Puts();
+#endif
- printf( " Listen = %s\n", Conf_ListenAddress );
pwd = getpwuid( Conf_UID );
if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name );
else printf( " ServerUID = %ld\n", (long)Conf_UID );
printf( " NoDNS = %s\n", yesno_to_str(Conf_NoDNS));
#ifdef WANT_IPV6
- printf(" ListenIPv6 = %s\n", yesno_to_str(Conf_ListenIPv6));
- printf(" ListenIPv4 = %s\n", yesno_to_str(Conf_ListenIPv4));
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
#endif
printf( " Name = %s\n", Conf_Server[i].name );
printf( " Host = %s\n", Conf_Server[i].host );
printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
+#ifdef SSL_SUPPORT
+ printf( " SSLConnect = %s\n", Conf_Server[i].SSLConnect?"yes":"no");
+#endif
printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
+ printf( " ServiceMask = %s\n", Conf_Server[i].svs_mask);
printf( " Group = %d\n", Conf_Server[i].group );
printf( " Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no");
}
printf( " Topic = %s\n\n", topic ? topic : "");
}
- return 0;
+ return (config_valid ? 0 : 1);
} /* Conf_Test */
} /* Conf_AddServer */
+/**
+ * Check if the given nick name is an service
+ */
+GLOBAL bool
+Conf_IsService(int ConfServer, char *Nick)
+{
+ return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick);
+} /* Conf_IsService */
+
+
static void
Set_Defaults( bool InitServers )
{
strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile ));
- strcpy( Conf_ListenAddress, "" );
-
+ free(Conf_ListenAddress);
+ Conf_ListenAddress = NULL;
Conf_UID = Conf_GID = 0;
Conf_PingTimeout = 120;
Conf_OperServerMode = false;
Conf_ConnectIPv4 = true;
- Conf_ListenIPv4 = true;
Conf_ConnectIPv6 = true;
- Conf_ListenIPv6 = true;
Conf_MaxConnections = 0;
Conf_MaxConnectionsIP = 5;
strcpy( section, "" );
Init_Server_Struct( &New_Server );
New_Server_Idx = NONE;
-
+#ifdef SSL_SUPPORT
+ ConfSSL_Init();
+#endif
/* Read configuration file */
while( true ) {
if( ! fgets( str, LINE_LEN, fd )) break;
exit( 1 );
}
}
+
+ if (!Conf_ListenAddress)
+ Conf_ListenAddress = strdup_warn(DEFAULT_LISTEN_ADDRSTR);
+
+ if (!Conf_ListenAddress) {
+ Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
+ exit(1);
+ }
return true;
} /* Read_Config */
}
#ifdef WANT_IPV6
/* the default setting for all the WANT_IPV6 special options is 'true' */
- if( strcasecmp( Var, "ListenIPv6" ) == 0 ) {
- /* listen on ipv6 sockets, if available? */
- Conf_ListenIPv6 = Check_ArgIsTrue( Arg );
- return;
- }
- if( strcasecmp( Var, "ListenIPv4" ) == 0 ) {
- /*
- * listen on ipv4 sockets, if available?
- * this allows "ipv6-only" setups.
- */
- Conf_ListenIPv4 = Check_ArgIsTrue( Arg );
- return;
- }
if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
/* connect to other hosts using ipv6, if they have an AAAA record? */
Conf_ConnectIPv6 = Check_ArgIsTrue( Arg );
if( strcasecmp( Var, "Listen" ) == 0 ) {
/* IP-Address to bind sockets */
- len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress ));
- if (len >= sizeof( Conf_ListenAddress ))
- Config_Error_TooLong( Line, Var );
+ if (Conf_ListenAddress) {
+ Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
+ return;
+ }
+ Conf_ListenAddress = strdup_warn(Arg);
+ /*
+ * if allocation fails, we're in trouble:
+ * we cannot ignore the error -- otherwise ngircd
+ * would listen on all interfaces.
+ */
+ if (!Conf_ListenAddress) {
+ Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
+ exit(1);
+ }
return;
}
- Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
- NGIRCd_ConfFile, Line, Var );
+#ifdef SSL_SUPPORT
+ if( strcasecmp( Var, "SSLPorts" ) == 0 ) {
+ ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
+ return;
+ }
+
+ if( strcasecmp( Var, "SSLKeyFile" ) == 0 ) {
+ assert(Conf_SSLOptions.KeyFile == NULL );
+ Conf_SSLOptions.KeyFile = strdup_warn(Arg);
+ return;
+ }
+ if( strcasecmp( Var, "SSLCertFile" ) == 0 ) {
+ assert(Conf_SSLOptions.CertFile == NULL );
+ Conf_SSLOptions.CertFile = strdup_warn(Arg);
+ return;
+ }
+
+ if( strcasecmp( Var, "SSLKeyFilePassword" ) == 0 ) {
+ assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
+ if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
+ Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Could not copy %s: %s!",
+ NGIRCd_ConfFile, Line, Var, strerror(errno));
+ return;
+ }
+ if( strcasecmp( Var, "SSLDHFile" ) == 0 ) {
+ assert(Conf_SSLOptions.DHFile == NULL);
+ Conf_SSLOptions.DHFile = strdup_warn( Arg );
+ return;
+ }
+#endif
+ Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
+ NGIRCd_ConfFile, Line, Var);
} /* Handle_GLOBAL */
NGIRCd_ConfFile, Line, port );
return;
}
+#ifdef SSL_SUPPORT
+ if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
+ New_Server.SSLConnect = Check_ArgIsTrue(Arg);
+ return;
+ }
+#endif
if( strcasecmp( Var, "Group" ) == 0 ) {
/* Server group */
#ifdef HAVE_ISDIGIT
New_Server.flags |= CONF_SFLAG_DISABLED;
return;
}
+ if (strcasecmp(Var, "ServiceMask") == 0) {
+ len = strlcpy(New_Server.svs_mask, ngt_LowerStr(Arg),
+ sizeof(New_Server.svs_mask));
+ if (len >= sizeof(New_Server.svs_mask))
+ Config_Error_TooLong(Line, Var);
+ return;
+ }
Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var );
} /* Handle_CHANNEL */
-static void
+static bool
Validate_Config(bool Configtest, bool Rehash)
{
/* Validate configuration settings. */
#ifdef DEBUG
int i, servers, servers_once;
#endif
+ bool config_valid = true;
char *ptr;
/* Validate configured server name, see RFC 2812 section 2.3.1 */
if (!Conf_ServerName[0]) {
/* No server name configured! */
+ config_valid = false;
Config_Error(LOG_ALERT,
"No (valid) server name configured in \"%s\" (section 'Global': 'Name')!",
NGIRCd_ConfFile);
if (Conf_ServerName[0] && !strchr(Conf_ServerName, '.')) {
/* No dot in server name! */
+ config_valid = false;
Config_Error(LOG_ALERT,
"Invalid server name configured in \"%s\" (section 'Global': 'Name'): Dot missing!",
NGIRCd_ConfFile);
#ifdef STRICT_RFC
if (!Conf_ServerAdminMail[0]) {
/* No administrative contact configured! */
+ config_valid = false;
Config_Error(LOG_ALERT,
"No administrator email address configured in \"%s\" ('AdminEMail')!",
NGIRCd_ConfFile);
"No administrative information configured but required by RFC!");
}
-#ifdef WANT_IPV6
- if (!Conf_ListenIPv4 && !Conf_ListenIPv6)
- Config_Error(LOG_ALERT,
- "Both \"ListenIPv4\" and \"ListenIPv6\" are set to 'no'; no network protocol available!");
-
- if (!Conf_ConnectIPv4 && !Conf_ConnectIPv6)
- Config_Error(LOG_ALERT,
- "Both \"ConnectIPv4\" and \"ConnectIPv6\" are set to 'no'; ngircd will fail to connect to other irc servers");
-#endif
-
#ifdef DEBUG
servers = servers_once = 0;
for (i = 0; i < MAX_SERVERS; i++) {
"Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
#endif
+
+ return config_valid;
} /* Validate_Config */