#define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
#endif
+#ifdef HAVE_LIBSSL
+#define DEFAULT_CIPHERS "HIGH:!aNULL:@STRENGTH"
+#endif
+#ifdef HAVE_LIBGNUTLS
+#define DEFAULT_CIPHERS "SECURE128"
+#endif
#ifdef SSL_SUPPORT
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
array_free(&Conf_SSLOptions.ListenPorts);
+
+ free(Conf_SSLOptions.CipherList);
+ Conf_SSLOptions.CipherList = NULL;
}
/**
* Parse a comma separated string into an array of port numbers (integers).
*/
static void
-ports_parse(array *a, int Line, char *Arg)
+ports_parse(array *a, const char *File, int Line, char *Arg)
{
char *ptr;
int port;
port16 = (UINT16) port;
if (!array_catb(a, (char*)&port16, sizeof port16))
Config_Error(LOG_ERR, "%s, line %d Could not add port number %ld: %s",
- NGIRCd_ConfFile, Line, port, strerror(errno));
+ File, Line, port, strerror(errno));
} else {
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!",
- NGIRCd_ConfFile, Line, port );
+ File, Line, port );
}
ptr = strtok( NULL, "," );
printf(" MotdPhrase = %s\n", array_bytes(&Conf_Motd)
? (const char*) array_start(&Conf_Motd) : "");
}
+ printf(" Network = %s\n", Conf_Network);
#ifndef PAM
printf(" Password = %s\n", Conf_ServerPwd);
#endif
puts("");
puts("[OPTIONS]");
+ printf(" AllowedChannelTypes = %s\n", Conf_AllowedChannelTypes);
printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper));
printf(" ChrootDir = %s\n", Conf_Chroot);
printf(" CloakHost = %s\n", Conf_CloakHost);
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
#endif
+ printf(" DefaultUserModes = %s\n", Conf_DefaultUserModes);
printf(" DNS = %s\n", yesno_to_str(Conf_DNS));
#ifdef IDENT
printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
printf(" PAMIsOptional = %s\n", yesno_to_str(Conf_PAMIsOptional));
#endif
- printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
#ifndef STRICT_RFC
printf(" RequireAuthPing = %s\n", yesno_to_str(Conf_AuthPing));
#endif
puts("[SSL]");
printf(" CertFile = %s\n", Conf_SSLOptions.CertFile
? Conf_SSLOptions.CertFile : "");
+ printf(" CipherList = %s\n", Conf_SSLOptions.CipherList ?
+ Conf_SSLOptions.CipherList : DEFAULT_CIPHERS);
printf(" DHFile = %s\n", Conf_SSLOptions.DHFile
? Conf_SSLOptions.DHFile : "");
printf(" KeyFile = %s\n", Conf_SSLOptions.KeyFile
/* "Short" connection, enforce "ConnectRetry"
* but randomize it a little bit: 15 seconds. */
Conf_Server[i].lasttry =
+#ifdef HAVE_ARC4RANDOM
+ t + (arc4random() % 15);
+#else
t + rand() / (RAND_MAX / 15);
+#endif
}
}
}
strcpy(Conf_ServerAdminMail, "");
snprintf(Conf_ServerInfo, sizeof Conf_ServerInfo, "%s %s",
PACKAGE_NAME, PACKAGE_VERSION);
+ strcpy(Conf_Network, "");
free(Conf_ListenAddress);
Conf_ListenAddress = NULL;
array_free(&Conf_ListenPorts);
Conf_PongTimeout = 20;
/* Options */
+ strlcpy(Conf_AllowedChannelTypes, CHANTYPES,
+ sizeof(Conf_AllowedChannelTypes));
Conf_AllowRemoteOper = false;
#ifndef STRICT_RFC
Conf_AuthPing = false;
#else
Conf_ConnectIPv6 = false;
#endif
+ strcpy(Conf_DefaultUserModes, "");
Conf_DNS = true;
#ifdef IDENTAUTH
Conf_Ident = true;
Conf_PAM = false;
#endif
Conf_PAMIsOptional = false;
- Conf_PredefChannelsOnly = false;
#ifdef SYSLOG
Conf_ScrubCTCP = false;
#ifdef LOG_LOCAL5
CheckFileReadable("CertFile", Conf_SSLOptions.CertFile);
CheckFileReadable("DHFile", Conf_SSLOptions.DHFile);
CheckFileReadable("KeyFile", Conf_SSLOptions.KeyFile);
+
+ /* Set the default ciphers if none were configured */
+ if (!Conf_SSLOptions.CipherList)
+ Conf_SSLOptions.CipherList = strdup_warn(DEFAULT_CIPHERS);
#endif
return true;
/* Read configuration file */
section[0] = '\0';
while (true) {
- if (!fgets(str, LINE_LEN, fd))
+ if (!fgets(str, sizeof(str), fd))
break;
ngt_TrimStr(str);
line++;
if (str[0] == ';' || str[0] == '#' || str[0] == '\0')
continue;
+ if (strlen(str) >= sizeof(str) - 1) {
+ Config_Error(LOG_WARNING, "%s, line %d too long!",
+ File, line);
+ continue;
+ }
+
/* Is this the beginning of a new section? */
if ((str[0] == '[') && (str[strlen(str) - 1] == ']')) {
strlcpy(section, str, sizeof(section));
Config_Error(LOG_ERR,
"%s, line %d: Unknown section \"%s\"!",
- NGIRCd_ConfFile, line, section);
+ File, line, section);
section[0] = 0x1;
}
if (section[0] == 0x1)
ptr = strchr(str, '=');
if (!ptr) {
Config_Error(LOG_ERR, "%s, line %d: Syntax error!",
- NGIRCd_ConfFile, line);
+ File, line);
continue;
}
*ptr = '\0';
else
Config_Error(LOG_ERR,
"%s, line %d: Variable \"%s\" outside section!",
- NGIRCd_ConfFile, line, var);
+ File, line, var);
}
}
* @returns New configured maximum nickname length.
*/
static unsigned int
-Handle_MaxNickLength(int Line, const char *Arg)
+Handle_MaxNickLength(const char *File, int Line, const char *Arg)
{
unsigned new;
if (new > CLIENT_NICK_LEN) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"MaxNickLength\" exceeds %u!",
- NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1);
+ File, Line, CLIENT_NICK_LEN - 1);
return CLIENT_NICK_LEN;
}
if (new < 2) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"MaxNickLength\" must be at least 1!",
- NGIRCd_ConfFile, Line);
+ File, Line);
return 2;
}
return new;
* Output a warning messages if IDENT is configured but not compiled in.
*/
static void
-WarnIdent(int UNUSED Line)
+WarnIdent(const char UNUSED *File, int UNUSED Line)
{
#ifndef IDENTAUTH
if (Conf_Ident) {
/* user has enabled ident lookups explicitly, but ... */
Config_Error(LOG_WARNING,
"%s: line %d: \"Ident = yes\", but ngircd was built without IDENT support!",
- NGIRCd_ConfFile, Line);
+ File, Line);
}
#endif
}
* Output a warning messages if IPv6 is configured but not compiled in.
*/
static void
-WarnIPv6(int UNUSED Line)
+WarnIPv6(const char UNUSED *File, int UNUSED Line)
{
#ifndef WANT_IPV6
if (Conf_ConnectIPv6) {
/* user has enabled IPv6 explicitly, but ... */
Config_Error(LOG_WARNING,
"%s: line %d: \"ConnectIPv6 = yes\", but ngircd was built without IPv6 support!",
- NGIRCd_ConfFile, Line);
+ File, Line);
}
#endif
}
* Output a warning messages if PAM is configured but not compiled in.
*/
static void
-WarnPAM(int UNUSED Line)
+WarnPAM(const char UNUSED *File, int UNUSED Line)
{
#ifndef PAM
if (Conf_PAM) {
Config_Error(LOG_WARNING,
"%s: line %d: \"PAM = yes\", but ngircd was built without PAM support!",
- NGIRCd_ConfFile, Line);
+ File, Line);
}
#endif
}
struct group *grp;
size_t len;
const char *section;
+ char *ptr;
assert(File != NULL);
assert(Line > 0);
len = strlen(Arg);
if (len == 0)
return;
- if (len >= LINE_LEN) {
+ if (len >= 127) {
Config_Error_TooLong(File, Line, Var);
return;
}
if (!array_copyb(&Conf_Motd, Arg, len + 1))
Config_Error(LOG_WARNING,
"%s, line %d: Could not append MotdPhrase: %s",
- NGIRCd_ConfFile, Line, strerror(errno));
+ File, Line, strerror(errno));
Using_MotdFile = false;
return;
}
+ if (strcasecmp(Var, "Network") == 0) {
+ len = strlcpy(Conf_Network, Arg, sizeof(Conf_Network));
+ if (len >= sizeof(Conf_Network))
+ Config_Error_TooLong(File, Line, Var);
+ ptr = strchr(Conf_Network, ' ');
+ if (ptr) {
+ Config_Error(LOG_WARNING,
+ "%s, line %d: \"Network\" can't contain spaces!",
+ File, Line);
+ *ptr = '\0';
+ }
+ return;
+ }
if(strcasecmp(Var, "Password") == 0) {
len = strlcpy(Conf_ServerPwd, Arg, sizeof(Conf_ServerPwd));
if (len >= sizeof(Conf_ServerPwd))
return;
}
if (strcasecmp(Var, "Ports") == 0) {
- ports_parse(&Conf_ListenPorts, Line, Arg);
+ ports_parse(&Conf_ListenPorts, File, Line, Arg);
return;
}
if (strcasecmp(Var, "ServerGID") == 0) {
if (!Conf_GID && strcmp(Arg, "0"))
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"%s\" is not a valid group name or ID!",
- NGIRCd_ConfFile, Line, Var);
+ File, Line, Var);
}
return;
}
if (!Conf_UID && strcmp(Arg, "0"))
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"%s\" is not a valid user name or ID!",
- NGIRCd_ConfFile, Line, Var);
+ File, Line, Var);
}
return;
}
* after marking it "deprecated"). */
Config_Error(LOG_WARNING,
"%s, line %d (section \"Global\"): \"No\"-Prefix is deprecated, use \"%s = %s\" in [Options] section!",
- NGIRCd_ConfFile, Line, NoNo(Var), InvertArg(Arg));
+ File, Line, NoNo(Var), InvertArg(Arg));
if (strcasecmp(Var, "NoIdent") == 0)
- WarnIdent(Line);
+ WarnIdent(File, Line);
else if (strcasecmp(Var, "NoPam") == 0)
- WarnPAM(Line);
+ WarnPAM(File, Line);
return;
}
if ((section = CheckLegacyGlobalOption(File, Line, Var, Arg))) {
if (strncasecmp(Var, "SSL", 3) == 0) {
Config_Error(LOG_WARNING,
"%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s and rename to \"%s\"!",
- NGIRCd_ConfFile, Line, Var, section,
+ File, Line, Var, section,
Var + 3);
} else {
Config_Error(LOG_WARNING,
"%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s!",
- NGIRCd_ConfFile, Line, Var, section);
+ File, Line, Var, section);
}
return;
}
if (Conf_ConnectRetry < 5) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"ConnectRetry\" too low!",
- NGIRCd_ConfFile, Line);
+ File, Line);
Conf_ConnectRetry = 5;
}
return;
return;
}
if (strcasecmp(Var, "MaxNickLength") == 0) {
- Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg);
+ Conf_MaxNickLength = Handle_MaxNickLength(File, Line, Arg);
return;
}
if (strcasecmp(Var, "MaxListSize") == 0) {
if (Conf_PingTimeout < 5) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"PingTimeout\" too low!",
- NGIRCd_ConfFile, Line);
+ File, Line);
Conf_PingTimeout = 5;
}
return;
if (Conf_PongTimeout < 5) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"PongTimeout\" too low!",
- NGIRCd_ConfFile, Line);
+ File, Line);
Conf_PongTimeout = 5;
}
return;
Handle_OPTIONS(const char *File, int Line, char *Var, char *Arg)
{
size_t len;
+ char *p;
assert(File != NULL);
assert(Line > 0);
assert(Var != NULL);
assert(Arg != NULL);
+ if (strcasecmp(Var, "AllowedChannelTypes") == 0) {
+ p = Arg;
+ Conf_AllowedChannelTypes[0] = '\0';
+ while (*p) {
+ if (strchr(Conf_AllowedChannelTypes, *p)) {
+ /* Prefix is already included; ignore it */
+ p++;
+ continue;
+ }
+
+ if (strchr(CHANTYPES, *p)) {
+ len = strlen(Conf_AllowedChannelTypes) + 1;
+ assert(len < sizeof(Conf_AllowedChannelTypes));
+ Conf_AllowedChannelTypes[len - 1] = *p;
+ Conf_AllowedChannelTypes[len] = '\0';
+ } else {
+ Config_Error(LOG_WARNING,
+ "%s, line %d: Unknown channel prefix \"%c\" in \"AllowedChannelTypes\"!",
+ File, Line, *p);
+ }
+ p++;
+ }
+ return;
+ }
if (strcasecmp(Var, "AllowRemoteOper") == 0) {
Conf_AllowRemoteOper = Check_ArgIsTrue(Arg);
return;
}
if (strcasecmp(Var, "ConnectIPv6") == 0) {
Conf_ConnectIPv6 = Check_ArgIsTrue(Arg);
- WarnIPv6(Line);
+ WarnIPv6(File, Line);
return;
}
if (strcasecmp(Var, "ConnectIPv4") == 0) {
Conf_ConnectIPv4 = Check_ArgIsTrue(Arg);
return;
}
+ if (strcasecmp(Var, "DefaultUserModes") == 0) {
+ p = Arg;
+ Conf_DefaultUserModes[0] = '\0';
+ while (*p) {
+ if (strchr(Conf_DefaultUserModes, *p)) {
+ /* Mode is already included; ignore it */
+ p++;
+ continue;
+ }
+
+ if (strchr(USERMODES, *p)) {
+ len = strlen(Conf_DefaultUserModes) + 1;
+ assert(len < sizeof(Conf_DefaultUserModes));
+ Conf_DefaultUserModes[len - 1] = *p;
+ Conf_DefaultUserModes[len] = '\0';
+ } else {
+ Config_Error(LOG_WARNING,
+ "%s, line %d: Unknown user mode \"%c\" in \"DefaultUserModes\"!",
+ File, Line, *p);
+ }
+ p++;
+ }
+ return;
+ }
if (strcasecmp(Var, "DNS") == 0) {
Conf_DNS = Check_ArgIsTrue(Arg);
return;
}
if (strcasecmp(Var, "Ident") == 0) {
Conf_Ident = Check_ArgIsTrue(Arg);
- WarnIdent(Line);
+ WarnIdent(File, Line);
return;
}
if (strcasecmp(Var, "IncludeDir") == 0) {
}
if (strcasecmp(Var, "PAM") == 0) {
Conf_PAM = Check_ArgIsTrue(Arg);
- WarnPAM(Line);
+ WarnPAM(File, Line);
return;
}
if (strcasecmp(Var, "PAMIsOptional") == 0 ) {
return;
}
if (strcasecmp(Var, "PredefChannelsOnly") == 0) {
- Conf_PredefChannelsOnly = Check_ArgIsTrue(Arg);
+ /*
+ * TODO: This section and support for "PredefChannelsOnly"
+ * could be removed starting with ngIRCd release 22 (one
+ * release after marking it "deprecated") ...
+ */
+ Config_Error(LOG_WARNING,
+ "%s, line %d (section \"Options\"): \"%s\" is deprecated, please use \"AllowedChannelTypes\"!",
+ File, Line, Var);
+ if (Check_ArgIsTrue(Arg))
+ Conf_AllowedChannelTypes[0] = '\0';
+ else
+ strlcpy(Conf_AllowedChannelTypes, CHANTYPES,
+ sizeof(Conf_AllowedChannelTypes));
return;
}
#ifndef STRICT_RFC
return;
}
if (strcasecmp(Var, "Ports") == 0) {
- ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
+ ports_parse(&Conf_SSLOptions.ListenPorts, File, Line, Arg);
+ return;
+ }
+ if (strcasecmp(Var, "CipherList") == 0) {
+ assert(Conf_SSLOptions.CipherList == NULL);
+ Conf_SSLOptions.CipherList = strdup_warn(Arg);
return;
}
return;
Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
- NGIRCd_ConfFile, Line, Arg);
+ File, Line, Arg);
return;
}
if( strcasecmp( Var, "MyPassword" ) == 0 ) {
/* Password of this server which is sent to the peer */
if (*Arg == ':') {
Config_Error(LOG_ERR,
- "%s, line %d (section \"Server\"): MyPassword must not start with ':'!",
- NGIRCd_ConfFile, Line);
+ "%s, line %d (section \"Server\"): MyPassword must not start with ':'!",
+ File, Line);
}
len = strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in ));
if (len >= sizeof( New_Server.pwd_in ))
New_Server.port = (UINT16)port;
else
Config_Error(LOG_ERR,
- "%s, line %d (section \"Server\"): Illegal port number %ld!",
- NGIRCd_ConfFile, Line, port );
+ "%s, line %d (section \"Server\"): Illegal port number %ld!",
+ File, Line, port );
return;
}
#ifdef SSL_SUPPORT