]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conf.c
Add support for arc4random
[ngircd-alex.git] / src / ngircd / conf.c
index c08183de9c1c94861b6f646bdbf341615391a652..d337947d9104eac1a9ef2a7da45b9132aef06f22 100644 (file)
@@ -93,6 +93,12 @@ static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
 #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
 
@@ -117,6 +123,9 @@ ConfSSL_Init(void)
        array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
 
        array_free(&Conf_SSLOptions.ListenPorts);
+
+       free(Conf_SSLOptions.CipherList);
+       Conf_SSLOptions.CipherList = NULL;
 }
 
 /**
@@ -317,7 +326,7 @@ opers_puts(void)
  * This function waits for a keypress of the user when stdin/stdout are valid
  * tty's ("you can read our nice message and we can read in your keypress").
  *
- * @return     0 on succes, 1 on failure(s); therefore the result code can
+ * @return     0 on success, 1 on failure(s); therefore the result code can
  *             directly be used by exit() when running "ngircd --configtest".
  */
 GLOBAL int
@@ -391,6 +400,7 @@ Conf_Test( void )
        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);
@@ -401,6 +411,7 @@ Conf_Test( void )
        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));
@@ -415,7 +426,6 @@ Conf_Test( void )
        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
@@ -431,6 +441,8 @@ Conf_Test( void )
        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
@@ -521,7 +533,11 @@ Conf_UnsetServer( CONN_ID Idx )
                                /* "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
                        }
                }
        }
@@ -758,6 +774,8 @@ Set_Defaults(bool InitServers)
        Conf_PongTimeout = 20;
 
        /* Options */
+       strlcpy(Conf_AllowedChannelTypes, CHANTYPES,
+               sizeof(Conf_AllowedChannelTypes));
        Conf_AllowRemoteOper = false;
 #ifndef STRICT_RFC
        Conf_AuthPing = false;
@@ -774,6 +792,7 @@ Set_Defaults(bool InitServers)
 #else
        Conf_ConnectIPv6 = false;
 #endif
+       strcpy(Conf_DefaultUserModes, "");
        Conf_DNS = true;
 #ifdef IDENTAUTH
        Conf_Ident = true;
@@ -792,7 +811,6 @@ Set_Defaults(bool InitServers)
        Conf_PAM = false;
 #endif
        Conf_PAMIsOptional = false;
-       Conf_PredefChannelsOnly = false;
 #ifdef SYSLOG
        Conf_ScrubCTCP = false;
 #ifdef LOG_LOCAL5
@@ -827,7 +845,7 @@ no_listenports(void)
 /**
  * Read contents of a text file into an array.
  *
- * This function is used to read the MOTD and help text file, for exampe.
+ * This function is used to read the MOTD and help text file, for example.
  *
  * @param filename     Name of the file to read.
  * @return             true, when the file has been read in.
@@ -947,33 +965,39 @@ Read_Config(bool TestOnly, bool IsStarting)
        fclose(fd);
 
        if (Conf_IncludeDir[0]) {
-               /* Include further configuration files, if any */
                dh = opendir(Conf_IncludeDir);
-               if (dh) {
-                       while ((entry = readdir(dh)) != NULL) {
-                               ptr = strrchr(entry->d_name, '.');
-                               if (!ptr || strcasecmp(ptr, ".conf") != 0)
-                                       continue;
-                               snprintf(file, sizeof(file), "%s/%s",
-                                        Conf_IncludeDir, entry->d_name);
-                               if (TestOnly)
-                                       Config_Error(LOG_INFO,
-                                                    "Reading configuration from \"%s\" ...",
-                                                    file);
-                               fd = fopen(file, "r");
-                               if (fd) {
-                                       Read_Config_File(file, fd);
-                                       fclose(fd);
-                               } else
-                                       Config_Error(LOG_ALERT,
-                                                    "Can't read configuration \"%s\": %s",
-                                                    file, strerror(errno));
-                       }
-                       closedir(dh);
-               } else
+               if (!dh)
                        Config_Error(LOG_ALERT,
                                     "Can't open include directory \"%s\": %s",
                                     Conf_IncludeDir, strerror(errno));
+       } else {
+               strlcpy(Conf_IncludeDir, SYSCONFDIR, sizeof(Conf_IncludeDir));
+               strlcat(Conf_IncludeDir, CONFIG_DIR, sizeof(Conf_IncludeDir));
+               dh = opendir(Conf_IncludeDir);
+       }
+
+       /* Include further configuration files, if IncludeDir is available */
+       if (dh) {
+               while ((entry = readdir(dh)) != NULL) {
+                       ptr = strrchr(entry->d_name, '.');
+                       if (!ptr || strcasecmp(ptr, ".conf") != 0)
+                               continue;
+                       snprintf(file, sizeof(file), "%s/%s",
+                                Conf_IncludeDir, entry->d_name);
+                       if (TestOnly)
+                               Config_Error(LOG_INFO,
+                                            "Reading configuration from \"%s\" ...",
+                                            file);
+                       fd = fopen(file, "r");
+                       if (fd) {
+                               Read_Config_File(file, fd);
+                               fclose(fd);
+                       } else
+                               Config_Error(LOG_ALERT,
+                                            "Can't read configuration \"%s\": %s",
+                                            file, strerror(errno));
+               }
+               closedir(dh);
        }
 
        /* Check if there is still a server to add */
@@ -1018,6 +1042,10 @@ Read_Config(bool TestOnly, bool IsStarting)
        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;
@@ -1627,12 +1655,37 @@ static void
 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;
@@ -1674,6 +1727,30 @@ Handle_OPTIONS(const char *File, int Line, char *Var, char *Arg)
                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;
@@ -1725,7 +1802,19 @@ Handle_OPTIONS(const char *File, int Line, char *Var, char *Arg)
                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
@@ -1799,6 +1888,11 @@ Handle_SSL(const char *File, int Line, char *Var, char *Arg)
                ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
                return;
        }
+       if (strcasecmp(Var, "CipherList") == 0) {
+               assert(Conf_SSLOptions.CipherList == NULL);
+               Conf_SSLOptions.CipherList = strdup_warn(Arg);
+               return;
+       }
 
        Config_Error_Section(File, Line, Var, "SSL");
 }
@@ -2275,7 +2369,7 @@ Conf_DebugDump(void)
 #endif
 
 /**
- * Initialize server configuration structur to default values.
+ * Initialize server configuration structure to default values.
  *
  * @param Server       Pointer to server structure to initialize.
  */