Accept 0600 and 0640 for server private key permissions.
[silc.git] / apps / silcd / serverconfig.c
index 94f1e7dd0c626761e433515351502784dc48137c..30d76af3516cae4c81cbb60a718e938cc66fadf3 100644 (file)
@@ -2,14 +2,13 @@
 
   serverconfig.c
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   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.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +20,7 @@
 
 #include "serverincludes.h"
 #include "server_internal.h"
+#include <dirent.h>
 
 #if 0
 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
 /* Free the authentication fields in the specified struct
  * Expands to two instructions */
 #define CONFIG_FREE_AUTH(__section__)                  \
-  silc_free(__section__->passphrase);                  \
-  if (__section__->publickeys)                         \
-    silc_hash_table_free(__section__->publickeys);
-
-static void my_free_public_key(void *key, void *context, void *user_data)
-{
-  silc_pkcs_public_key_free(context);
-}
+  silc_free(__section__->passphrase);
 
 /* Set default values to those parameters that have not been defined */
 static void
@@ -92,6 +85,11 @@ my_set_param_defaults(SilcServerConfigConnParams *params,
   SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
   SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
   SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
+  SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT);
+  SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
+  SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
+  SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
+  SET_PARAM_DEFAULT(chlimit, SILC_SERVER_CH_JOIN_LIMIT);
 
 #undef SET_PARAM_DEFAULT
 }
@@ -113,18 +111,34 @@ my_find_param(SilcServerConfig config, const char *name)
   return NULL;
 }
 
+/* SKR find callbcak */
+
+static void my_find_callback(SilcSKR skr, SilcSKRFind find,
+                            SilcSKRStatus status, SilcDList keys,
+                            void *context)
+{
+  SilcSKRStatus *s = context;
+
+  *s = status;
+  if (keys)
+    silc_dlist_uninit(keys);
+
+  silc_skr_find_free(find);
+}
+
 /* parse an authdata according to its auth method */
-static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
-                             void **auth_data, SilcUInt32 *auth_data_len)
+static SilcBool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
+                                 void **auth_data, SilcUInt32 *auth_data_len,
+                                 SilcSKRKeyUsage usage, void *key_context)
 {
   if (auth_meth == SILC_AUTH_PASSWORD) {
     /* p is a plain text password */
     if (auth_data && auth_data_len) {
       if (!silc_utf8_valid(p, strlen(p))) {
        *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
-                                              SILC_STRING_LANGUAGE);
+                                              SILC_STRING_LOCALE);
        *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
-       silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
+       silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
                         *auth_data_len);
       } else {
        *auth_data = (void *) strdup(p);
@@ -134,29 +148,84 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
   } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
     /* p is a public key file name */
     SilcPublicKey public_key;
+    SilcSKR skr = *auth_data;
+    SilcSKRFind find;
+    SilcSKRStatus status = SILC_SKR_NOT_FOUND;
 
-    if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
-      if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
-       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
-                              "Could not load public key file!"));
-       return FALSE;
-      }
+    if (!silc_pkcs_load_public_key(p, &public_key)) {
+      SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+                            "Could not load public key file!"));
+      return FALSE;
+    }
+
+    find = silc_skr_find_alloc();
+    silc_skr_find_set_public_key(find, public_key);
+    silc_skr_find_set_usage(find, usage);
+    if (!key_context)
+      silc_skr_find_set_context(find, SILC_32_TO_PTR(usage));
+    silc_skr_find(skr, NULL, find, my_find_callback, &status);
+    if (status == SILC_SKR_OK) {
+      /* Already added, ignore error */
+      silc_pkcs_public_key_free(public_key);
+      return TRUE;
+    }
 
-    /* The auth_data is a pointer to the hash table of public keys. */
-    if (auth_data) {
-      if (*auth_data == NULL)
-       *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
-                                          NULL, NULL,
-                                          my_free_public_key, NULL,
-                                          TRUE);
-      silc_hash_table_add(*auth_data, public_key, public_key);
+    /* Add the public key to repository */
+    status = silc_skr_add_public_key(skr, public_key, usage,
+                                    key_context ? key_context :
+                                    (void *)usage, NULL);
+    if (status != SILC_SKR_OK) {
+      SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
+      return FALSE;
     }
-  } else
-    abort();
+  }
 
   return TRUE;
 }
 
+static int my_parse_publickeydir(const char *dirname, void **auth_data,
+                                SilcSKRKeyUsage usage)
+{
+  int total = 0;
+  struct dirent *get_file;
+  DIR *dp;
+
+  if (!(dp = opendir(dirname))) {
+    SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+                          "Could not open directory \"%s\"", dirname));
+    return -1;
+  }
+
+  /* errors are not considered fatal */
+  while ((get_file = readdir(dp))) {
+    const char *filename = get_file->d_name;
+    char buf[1024];
+    int dirname_len = strlen(dirname), filename_len = strlen(filename);
+    struct stat check_file;
+
+    /* Ignore "." and "..", and take files only with ".pub" suffix. */
+    if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
+       (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
+      continue;
+
+    memset(buf, 0, sizeof(buf));
+    snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
+            (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
+
+    if (stat(buf, &check_file) < 0) {
+      SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
+                            strerror(errno)));
+    } else if (S_ISREG(check_file.st_mode)) {
+      if (my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL,
+                           usage, NULL))
+       total++;
+    }
+  }
+
+  SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
+  return total;
+}
+
 /* Callbacks */
 
 SILC_CONFIG_CALLBACK(fetch_generic)
@@ -164,15 +233,11 @@ SILC_CONFIG_CALLBACK(fetch_generic)
   SilcServerConfig config = (SilcServerConfig) context;
   int got_errno = 0;
 
-  if (!strcmp(name, "module_path")) {
-    CONFIG_IS_DOUBLE(config->module_path);
-    config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
-  }
-  else if (!strcmp(name, "prefer_passphrase_auth")) {
-    config->prefer_passphrase_auth = *(bool *)val;
+  if (!strcmp(name, "prefer_passphrase_auth")) {
+    config->prefer_passphrase_auth = *(SilcBool *)val;
   }
   else if (!strcmp(name, "require_reverse_lookup")) {
-    config->require_reverse_lookup = *(bool *)val;
+    config->require_reverse_lookup = *(SilcBool *)val;
   }
   else if (!strcmp(name, "connections_max")) {
     config->param.connections_max = (SilcUInt32) *(int *)val;
@@ -193,13 +258,13 @@ SILC_CONFIG_CALLBACK(fetch_generic)
     config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
   }
   else if (!strcmp(name, "reconnect_keep_trying")) {
-    config->param.reconnect_keep_trying = *(bool *)val;
+    config->param.reconnect_keep_trying = *(SilcBool *)val;
   }
   else if (!strcmp(name, "key_exchange_rekey")) {
     config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
   }
   else if (!strcmp(name, "key_exchange_pfs")) {
-    config->param.key_exchange_pfs = *(bool *)val;
+    config->param.key_exchange_pfs = *(SilcBool *)val;
   }
   else if (!strcmp(name, "channel_rekey_secs")) {
     config->channel_rekey_secs = (SilcUInt32) *(int *)val;
@@ -226,11 +291,56 @@ SILC_CONFIG_CALLBACK(fetch_generic)
       (*(char *)val ? strdup((char *) val) : NULL);
   }
   else if (!strcmp(name, "detach_disabled")) {
-    config->detach_disabled = *(bool *)val;
+    config->detach_disabled = *(SilcBool *)val;
   }
   else if (!strcmp(name, "detach_timeout")) {
     config->detach_timeout = (SilcUInt32) *(int *)val;
   }
+  else if (!strcmp(name, "qos")) {
+    config->param.qos = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "qos_rate_limit")) {
+    config->param.qos_rate_limit = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_bytes_limit")) {
+    config->param.qos_bytes_limit = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_limit_sec")) {
+    config->param.qos_limit_sec = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_limit_usec")) {
+    config->param.qos_limit_usec = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "channel_join_limit")) {
+    config->param.chlimit = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "debug_string")) {
+    CONFIG_IS_DOUBLE(config->debug_string);
+    config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
+  }
+  else if (!strcmp(name, "http_server")) {
+    config->httpd = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "http_server_ip")) {
+    CONFIG_IS_DOUBLE(config->httpd_ip);
+    config->httpd_ip = (*(char *)val ? strdup((char *) val) : NULL);
+  }
+  else if (!strcmp(name, "http_server_port")) {
+    int port = *(int *)val;
+    if ((port <= 0) || (port > 65535)) {
+      SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+                            "Invalid port number!"));
+      got_errno = SILC_CONFIG_EPRINTLINE;
+      goto got_err;
+    }
+    config->httpd_port = (SilcUInt16)port;
+  }
+  else if (!strcmp(name, "dynamic_server")) {
+    config->dynamic_server = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "local_channels")) {
+    config->local_channels = *(SilcBool *)val;
+  }
   else
     return SILC_CONFIG_EINTERNAL;
 
@@ -266,10 +376,6 @@ SILC_CONFIG_CALLBACK(fetch_cipher)
     CONFIG_IS_DOUBLE(tmp->name);
     tmp->name = strdup((char *) val);
   }
-  else if (!strcmp(name, "module")) {
-    CONFIG_IS_DOUBLE(tmp->module);
-    tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
-  }
   else if (!strcmp(name, "keylength")) {
     tmp->key_length = *(SilcUInt32 *)val;
   }
@@ -282,7 +388,6 @@ SILC_CONFIG_CALLBACK(fetch_cipher)
 
  got_err:
   silc_free(tmp->name);
-  silc_free(tmp->module);
   silc_free(tmp);
   config->tmp = NULL;
   return got_errno;
@@ -314,10 +419,6 @@ SILC_CONFIG_CALLBACK(fetch_hash)
     CONFIG_IS_DOUBLE(tmp->name);
     tmp->name = strdup((char *) val);
   }
-  else if (!strcmp(name, "module")) {
-    CONFIG_IS_DOUBLE(tmp->module);
-    tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
-  }
   else if (!strcmp(name, "blocklength")) {
     tmp->block_length = *(int *)val;
   }
@@ -330,7 +431,6 @@ SILC_CONFIG_CALLBACK(fetch_hash)
 
  got_err:
   silc_free(tmp->name);
-  silc_free(tmp->module);
   silc_free(tmp);
   config->tmp = NULL;
   return got_errno;
@@ -388,7 +488,7 @@ SILC_CONFIG_CALLBACK(fetch_pkcs)
   SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
                       type, name, context));
   if (type == SILC_CONFIG_ARG_BLOCK) {
-    /* check the temporary struct's fields */
+    /* Check the temporary struct's fields */
     if (!tmp) /* discard empty sub-blocks */
       return SILC_CONFIG_OK;
     if (!tmp->name) {
@@ -423,22 +523,40 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
   SilcServerConfigServerInfo *server_info = config->server_info;
 
-  /* if there isn't the struct alloc it */
+  SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
+                      type, name, context));
+
+  /* If there isn't the main struct alloc it */
   if (!server_info)
     config->server_info = server_info = (SilcServerConfigServerInfo *)
                silc_calloc(1, sizeof(*server_info));
 
   if (type == SILC_CONFIG_ARG_BLOCK) {
     if (!strcmp(name, "primary")) {
+      if (server_info->primary) {
+       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+                              "Double primary specification."));
+       got_errno = SILC_CONFIG_EPRINTLINE;
+       goto got_err;
+      }
       CONFIG_IS_DOUBLE(server_info->primary);
-      if (!tmp)
-       return SILC_CONFIG_OK;
+
+      /* now check the temporary struct, don't accept empty block and
+         make sure all fields are there */
+      if (!tmp || !tmp->server_ip || !tmp->port) {
+       got_errno = SILC_CONFIG_EMISSFIELDS;
+       goto got_err;
+      }
       server_info->primary = tmp;
       config->tmp = NULL;
       return SILC_CONFIG_OK;
     } else if (!strcmp(name, "secondary")) {
       if (!tmp)
        return SILC_CONFIG_OK;
+      if (!tmp || !tmp->server_ip || !tmp->port) {
+       got_errno = SILC_CONFIG_EMISSFIELDS;
+       goto got_err;
+      }
       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
       config->tmp = NULL;
       return SILC_CONFIG_OK;
@@ -457,6 +575,11 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
     CONFIG_IS_DOUBLE(tmp->server_ip);
     tmp->server_ip = strdup((char *) val);
   }
+  else if (!strcmp(name, "public_ip")) {
+    SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
+    CONFIG_IS_DOUBLE(tmp->public_ip);
+    tmp->public_ip = strdup((char *) val);
+  }
   else if (!strcmp(name, "port")) {
     int port = *(int *)val;
     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
@@ -502,36 +625,49 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   }
   else if (!strcmp(name, "publickey")) {
     char *file_tmp = (char *) val;
+    CONFIG_IS_DOUBLE(server_info->public_key);
 
-    /* try to load specified file, if fail stop config parsing */
-    if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
-                                  SILC_PKCS_FILE_PEM))
-      if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
-                                    SILC_PKCS_FILE_BIN)) {
-       SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
-       return SILC_CONFIG_EPRINTLINE;
-      }
+    /* Try to load specified file, if fail stop config parsing */
+    if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
+      SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
+      return SILC_CONFIG_EPRINTLINE;
+    }
   }
   else if (!strcmp(name, "privatekey")) {
+    struct stat st;
     char *file_tmp = (char *) val;
-
-    /* try to load specified file, if fail stop config parsing */
-    if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
-                                   SILC_PKCS_FILE_BIN))
-      if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
-                                     SILC_PKCS_FILE_PEM)) {
-       SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
-       return SILC_CONFIG_EPRINTLINE;
+    CONFIG_IS_DOUBLE(server_info->private_key);
+
+    /* Check the private key file permissions. */
+    if ((stat(file_tmp, &st)) != -1) {
+      if (((st.st_mode & 0777) != 0600) &&
+         ((st.st_mode & 0777) != 0640)) {
+       SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
+                             "file \"%s\".  The permissions must be "
+                             "0600 or 0640.", file_tmp));
+        return SILC_CONFIG_ESILENT;
       }
+    }
+
+    /* Try to load specified file, if fail stop config parsing */
+    if (!silc_pkcs_load_private_key(file_tmp, "", 0,
+                                   &server_info->private_key)) {
+      SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
+      return SILC_CONFIG_EPRINTLINE;
+    }
   }
   else
     return SILC_CONFIG_EINTERNAL;
   return SILC_CONFIG_OK;
 
  got_err:
-  silc_free(tmp);
-  silc_free(config->tmp);
-  config->tmp = NULL;
+  /* Here we need to check if tmp exists because this function handles
+   * misc data (multiple fields and single-only fields) */
+  if (tmp) {
+    silc_free(tmp->server_ip);
+    silc_free(tmp);
+    config->tmp = NULL;
+  }
   return got_errno;
 }
 
@@ -540,10 +676,10 @@ SILC_CONFIG_CALLBACK(fetch_logging)
   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
 
   if (!strcmp(name, "timestamp")) {
-    config->logging_timestamp = *(bool *)val;
+    config->logging_timestamp = *(SilcBool *)val;
   }
   else if (!strcmp(name, "quicklogs")) {
-    config->logging_quick = *(bool *)val;
+    config->logging_quick = *(SilcBool *)val;
   }
   else if (!strcmp(name, "flushdelay")) {
     int flushdelay = *(int *)val;
@@ -619,7 +755,10 @@ SILC_CONFIG_CALLBACK(fetch_connparam)
     config->tmp = NULL;
     return SILC_CONFIG_OK;
   }
-  SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
+  if (!tmp) {
+    SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
+    tmp->reconnect_keep_trying = TRUE;
+  }
 
   if (!strcmp(name, "name")) {
     CONFIG_IS_DOUBLE(tmp->name);
@@ -644,13 +783,13 @@ SILC_CONFIG_CALLBACK(fetch_connparam)
     tmp->reconnect_interval_max = *(SilcUInt32 *)val;
   }
   else if (!strcmp(name, "reconnect_keep_trying")) {
-    tmp->reconnect_keep_trying = *(bool *)val;
+    tmp->reconnect_keep_trying = *(SilcBool *)val;
   }
   else if (!strcmp(name, "key_exchange_rekey")) {
     tmp->key_exchange_rekey = *(SilcUInt32 *)val;
   }
   else if (!strcmp(name, "key_exchange_pfs")) {
-    tmp->key_exchange_pfs = *(bool *)val;
+    tmp->key_exchange_pfs = *(SilcBool *)val;
   }
   else if (!strcmp(name, "version_protocol")) {
     CONFIG_IS_DOUBLE(tmp->version_protocol);
@@ -666,7 +805,22 @@ SILC_CONFIG_CALLBACK(fetch_connparam)
       (*(char *)val ? strdup((char *) val) : NULL);
   }
   else if (!strcmp(name, "anonymous")) {
-    tmp->anonymous = *(bool *)val;
+    tmp->anonymous = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "qos")) {
+    tmp->qos = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "qos_rate_limit")) {
+    tmp->qos_rate_limit = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_bytes_limit")) {
+    tmp->qos_bytes_limit = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_limit_sec")) {
+    tmp->qos_limit_sec = *(SilcUInt32 *)val;
+  }
+  else if (!strcmp(name, "qos_limit_usec")) {
+    tmp->qos_limit_usec = *(SilcUInt32 *)val;
   }
   else
     return SILC_CONFIG_EINTERNAL;
@@ -705,18 +859,31 @@ SILC_CONFIG_CALLBACK(fetch_client)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
-                          &tmp->passphrase_len)) {
+                          (void *)&tmp->passphrase,
+                          &tmp->passphrase_len, 0, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
   }
   else if (!strcmp(name, "publickey")) {
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&config->server->repository, NULL,
+                          SILC_SKR_USAGE_AUTH |
+                          SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
+      got_errno = SILC_CONFIG_EPRINTLINE;
+      goto got_err;
+    }
+    tmp->publickeys = TRUE;
+  }
+  else if (!strcmp(name, "publickeydir")) {
+    if (my_parse_publickeydir((char *) val,
+                             (void *)&config->server->repository,
+                             SILC_SKR_USAGE_AUTH |
+                             SILC_SKR_USAGE_KEY_AGREEMENT) < 0) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
+    tmp->publickeys = TRUE;
   }
   else if (!strcmp(name, "params")) {
     CONFIG_IS_DOUBLE(tmp->param);
@@ -771,19 +938,20 @@ SILC_CONFIG_CALLBACK(fetch_admin)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
-                          &tmp->passphrase_len)) {
+                          (void *)&tmp->passphrase,
+                          &tmp->passphrase_len, 0, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
   }
   else if (!strcmp(name, "publickey")) {
-    CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&config->server->repository, NULL,
+                          SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
+    tmp->publickeys = TRUE;
   }
   else
     return SILC_CONFIG_EINTERNAL;
@@ -851,6 +1019,10 @@ SILC_CONFIG_CALLBACK(fetch_server)
     /* check the temporary struct's fields */
     if (!tmp) /* discard empty sub-blocks */
       return SILC_CONFIG_OK;
+    if (!tmp->host) {
+      got_errno = SILC_CONFIG_EMISSFIELDS;
+      goto got_err;
+    }
 
     /* the temporary struct is ok, append it to the list */
     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
@@ -867,8 +1039,8 @@ SILC_CONFIG_CALLBACK(fetch_server)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
-                          &tmp->passphrase_len)) {
+                          (void *)&tmp->passphrase,
+                          &tmp->passphrase_len, 0, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -876,10 +1048,13 @@ SILC_CONFIG_CALLBACK(fetch_server)
   else if (!strcmp(name, "publickey")) {
     CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&config->server->repository, NULL,
+                          SILC_SKR_USAGE_AUTH |
+                          SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
+    tmp->publickeys = TRUE;
   }
   else if (!strcmp(name, "params")) {
     CONFIG_IS_DOUBLE(tmp->param);
@@ -890,7 +1065,7 @@ SILC_CONFIG_CALLBACK(fetch_server)
     }
   }
   else if (!strcmp(name, "backup")) {
-    tmp->backup_router = *(bool *)val;
+    tmp->backup_router = *(SilcBool *)val;
   }
   else
     return SILC_CONFIG_EINTERNAL;
@@ -914,6 +1089,10 @@ SILC_CONFIG_CALLBACK(fetch_router)
   if (type == SILC_CONFIG_ARG_BLOCK) {
     if (!tmp) /* discard empty sub-blocks */
       return SILC_CONFIG_OK;
+    if (!tmp->host) {
+      got_errno = SILC_CONFIG_EMISSFIELDS;
+      goto got_err;
+    }
 
     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
     config->tmp = NULL;
@@ -939,8 +1118,8 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
-                          &tmp->passphrase_len)) {
+                          (void *)&tmp->passphrase,
+                          &tmp->passphrase_len, 0, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -948,10 +1127,13 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "publickey")) {
     CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&config->server->repository, NULL,
+                          SILC_SKR_USAGE_AUTH |
+                          SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
+    tmp->publickeys = TRUE;
   }
   else if (!strcmp(name, "params")) {
     CONFIG_IS_DOUBLE(tmp->param);
@@ -962,7 +1144,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
     }
   }
   else if (!strcmp(name, "initiator")) {
-    tmp->initiator = *(bool *)val;
+    tmp->initiator = *(SilcBool *)val;
   }
   else if (!strcmp(name, "backuphost")) {
     CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
@@ -981,7 +1163,10 @@ SILC_CONFIG_CALLBACK(fetch_router)
     tmp->backup_replace_port = (SilcUInt16) port;
   }
   else if (!strcmp(name, "backuplocal")) {
-    tmp->backup_local = *(bool *)val;
+    tmp->backup_local = *(SilcBool *)val;
+  }
+  else if (!strcmp(name, "dynamic_connection")) {
+    tmp->dynamic_connection = *(SilcBool *)val;
   }
   else
     return SILC_CONFIG_EINTERNAL;
@@ -999,7 +1184,6 @@ SILC_CONFIG_CALLBACK(fetch_router)
 
 /* known config options tables */
 static const SilcConfigTable table_general[] = {
-  { "module_path",             SILC_CONFIG_ARG_STRE,   fetch_generic,  NULL },
   { "prefer_passphrase_auth",  SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
   { "require_reverse_lookup",  SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
   { "connections_max",         SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
@@ -1019,12 +1203,23 @@ static const SilcConfigTable table_general[] = {
   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
   { "detach_disabled",         SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
   { "detach_timeout",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "qos",                     SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
+  { "qos_rate_limit",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "channel_join_limit",      SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "debug_string",                    SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
+  { "http_server",             SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
+  { "http_server_ip",                  SILC_CONFIG_ARG_STRE,   fetch_generic,  NULL },
+  { "http_server_port",                SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "dynamic_server",                  SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
+  { "local_channels",          SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
   { 0, 0, 0, 0 }
 };
 
 static const SilcConfigTable table_cipher[] = {
   { "name",            SILC_CONFIG_ARG_STR,    fetch_cipher,   NULL },
-  { "module",          SILC_CONFIG_ARG_STRE,   fetch_cipher,   NULL },
   { "keylength",       SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
   { "blocklength",     SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
   { 0, 0, 0, 0 }
@@ -1032,7 +1227,6 @@ static const SilcConfigTable table_cipher[] = {
 
 static const SilcConfigTable table_hash[] = {
   { "name",            SILC_CONFIG_ARG_STR,    fetch_hash,     NULL },
-  { "module",          SILC_CONFIG_ARG_STRE,   fetch_hash,     NULL },
   { "blocklength",     SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
   { "digestlength",    SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
   { 0, 0, 0, 0 }
@@ -1052,6 +1246,7 @@ static const SilcConfigTable table_pkcs[] = {
 
 static const SilcConfigTable table_serverinfo_c[] = {
   { "ip",              SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
+  { "public_ip",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
   { "port",            SILC_CONFIG_ARG_INT,    fetch_serverinfo, NULL},
   { 0, 0, 0, 0 }
 };
@@ -1107,6 +1302,11 @@ static const SilcConfigTable table_connparam[] = {
   { "version_software",               SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_connparam,        NULL },
   { "anonymous",               SILC_CONFIG_ARG_TOGGLE, fetch_connparam,        NULL },
+  { "qos",                    SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
+  { "qos_rate_limit",          SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
   { 0, 0, 0, 0 }
 };
 
@@ -1114,6 +1314,7 @@ static const SilcConfigTable table_client[] = {
   { "host",            SILC_CONFIG_ARG_STRE,   fetch_client,   NULL },
   { "passphrase",      SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
   { "publickey",       SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
+  { "publickeydir",    SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
   { "params",          SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
   { 0, 0, 0, 0 }
 };
@@ -1154,15 +1355,16 @@ static const SilcConfigTable table_routerconn[] = {
   { "backuphost",      SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
   { "backupport",      SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
   { "backuplocal",     SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
+  { "dynamic_connection",      SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
   { 0, 0, 0, 0 }
 };
 
 static const SilcConfigTable table_main[] = {
-  { "general",         SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
   { "cipher",          SILC_CONFIG_ARG_BLOCK,  fetch_cipher,  table_cipher },
   { "hash",            SILC_CONFIG_ARG_BLOCK,  fetch_hash,    table_hash },
   { "hmac",            SILC_CONFIG_ARG_BLOCK,  fetch_hmac,    table_hmac },
   { "pkcs",            SILC_CONFIG_ARG_BLOCK,  fetch_pkcs,    table_pkcs },
+  { "general",         SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
   { "serverinfo",      SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo },
   { "logging",         SILC_CONFIG_ARG_BLOCK,  NULL,          table_logging },
   { "connectionparams",        SILC_CONFIG_ARG_BLOCK,  fetch_connparam, table_connparam },
@@ -1191,12 +1393,106 @@ static void silc_server_config_set_defaults(SilcServerConfig config)
                               SILC_SERVER_CONNAUTH_TIMEOUT);
 }
 
+/* Check for correctness of the configuration */
+
+static SilcBool silc_server_config_check(SilcServerConfig config)
+{
+  SilcBool ret = TRUE;
+  SilcServerConfigServer *s;
+  SilcServerConfigRouter *r;
+  SilcBool b = FALSE;
+
+  /* ServerConfig is mandatory */
+  if (!config->server_info) {
+    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
+    ret = FALSE;
+  }
+
+  if (!config->server_info->public_key ||
+      !config->server_info->private_key) {
+    SILC_SERVER_LOG_ERROR(("\nError: Server keypair is missing"));
+    ret = FALSE;
+  }
+
+  if (!config->server_info->primary) {
+    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `Primary' "
+                          "in `ServerInfo'"));
+    ret = FALSE;
+  }
+
+  if (!config->server_info->primary->server_ip) {
+    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory field `Ip' "
+                          "in `Primary' in `ServerInfo'"));
+    ret = FALSE;
+  }
+
+  /* RouterConnection sanity checks */
+
+  if (config->routers && config->routers->backup_router == TRUE &&
+      !config->servers) {
+    SILC_SERVER_LOG_ERROR((
+         "\nError: First RouterConnection block must be primary router "
+        "connection. You have marked it incorrectly as backup router."));
+    ret = FALSE;
+  }
+  if (config->routers && config->routers->backup_router == TRUE &&
+      !config->servers && !config->routers->next) {
+    SILC_SERVER_LOG_ERROR((
+         "\nError: You have configured backup router but not primary router. "
+        "If backup router is configured also primary router must be "
+        "configured."));
+    ret = FALSE;
+  }
+
+  /* Backup router sanity checks */
+
+  for (r = config->routers; r; r = r->next) {
+    if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
+      SILC_SERVER_LOG_ERROR((
+          "\nError: Backup router connection incorrectly configured to use "
+         "primary and backup router as same host `%s'. They must not be "
+         "same host.", r->host));
+      ret = FALSE;
+    }
+
+    if (r->initiator == FALSE && r->port != 0) {
+      SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
+                               "specified. Ignoring Port value."));
+      r->port = 0;
+    }
+  }
+
+  /* ServerConnection sanity checks */
+
+  for (s = config->servers; s; s = s->next) {
+    if (s->backup_router) {
+      b = TRUE;
+      break;
+    }
+  }
+  if (b) {
+    for (s = config->servers; s; s = s->next) {
+      if (!s->backup_router) {
+       SILC_SERVER_LOG_ERROR((
+          "\nError: Your server is backup router but not all ServerConnection "
+         "blocks were marked as backup connections. They all must be "
+         "marked as backup connections."));
+       ret = FALSE;
+       break;
+      }
+    }
+  }
+
+  return ret;
+}
+
 /* Allocates a new configuration object, opens configuration file and
    parses it. The parsed data is returned to the newly allocated
    configuration object. The SilcServerConfig must be freed by calling
    the silc_server_config_destroy function. */
 
-SilcServerConfig silc_server_config_alloc(const char *filename)
+SilcServerConfig silc_server_config_alloc(const char *filename,
+                                         SilcServer server)
 {
   SilcServerConfig config_new;
   SilcConfigEntity ent;
@@ -1206,12 +1502,14 @@ SilcServerConfig silc_server_config_alloc(const char *filename)
 
   /* alloc a config object */
   config_new = silc_calloc(1, sizeof(*config_new));
-  config_new->refcount = 1;
   if (!config_new)
     return NULL;
 
   /* general config defaults */
+  config_new->refcount = 1;
   config_new->logging_timestamp = TRUE;
+  config_new->param.reconnect_keep_trying = TRUE;
+  config_new->server = server;
 
   /* obtain a config file object */
   file = silc_config_open(filename);
@@ -1243,21 +1541,22 @@ SilcServerConfig silc_server_config_alloc(const char *filename)
         SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
                               silc_config_strerror(ret)));
       linebuf = silc_config_read_line(file, line);
-      SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename,
-                            line, linebuf));
-      silc_free(linebuf);
+      if (linebuf) {
+       SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename,
+                              line, linebuf));
+       silc_free(linebuf);
+      }
     }
     silc_server_config_destroy(config_new);
+    silc_config_close(file);
     return NULL;
   }
 
   /* close (destroy) the file object */
   silc_config_close(file);
 
-  /* If config_new is incomplete, abort the object and return NULL */
-  if (!config_new->server_info) {
-    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
-                          "`server_info'"));
+  /* Check the configuration */
+  if (!silc_server_config_check(config_new)) {
     silc_server_config_destroy(config_new);
     return NULL;
   }
@@ -1306,10 +1605,11 @@ void silc_server_config_destroy(SilcServerConfig config)
   SILC_LOG_DEBUG(("Freeing config context"));
 
   /* Destroy general config stuff */
-  silc_free(config->module_path);
+  silc_free(config->debug_string);
   silc_free(config->param.version_protocol);
   silc_free(config->param.version_software);
   silc_free(config->param.version_software_vendor);
+  silc_free(config->httpd_ip);
 
   /* Destroy Logging channels */
   if (config->logging_info)
@@ -1346,8 +1646,10 @@ void silc_server_config_destroy(SilcServerConfig config)
     silc_free(si->group);
     silc_free(si->motd_file);
     silc_free(si->pid_file);
-    silc_pkcs_public_key_free(si->public_key);
-    silc_pkcs_private_key_free(si->private_key);
+    if (si->public_key)
+      silc_pkcs_public_key_free(si->public_key);
+    if (si->private_key)
+      silc_pkcs_private_key_free(si->private_key);
     silc_free(si);
   }
 
@@ -1356,12 +1658,10 @@ void silc_server_config_destroy(SilcServerConfig config)
   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
                                  config->cipher)
     silc_free(di->name);
-    silc_free(di->module);
     silc_free(di);
   }
   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
     silc_free(di->name);
-    silc_free(di->module);
     silc_free(di);
   }
   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
@@ -1419,7 +1719,7 @@ void silc_server_config_destroy(SilcServerConfig config)
 /* Registers configured ciphers. These can then be allocated by the
    server when needed. */
 
-bool silc_server_config_register_ciphers(SilcServer server)
+SilcBool silc_server_config_register_ciphers(SilcServer server)
 {
   SilcServerConfig config = server->config;
   SilcServerConfigCipher *cipher = config->cipher;
@@ -1445,69 +1745,6 @@ bool silc_server_config_register_ciphers(SilcServer server)
        silc_server_stop(server);
        exit(1);
       }
-    } else {
-#ifdef SILC_SIM
-      /* Load (try at least) the crypto SIM module */
-      char buf[1023], *alg_name;
-      SilcCipherObject cipher_obj;
-      SilcSim sim;
-
-      memset(&cipher_obj, 0, sizeof(cipher_obj));
-      cipher_obj.name = cipher->name;
-      cipher_obj.block_len = cipher->block_length;
-      cipher_obj.key_len = cipher->key_length * 8;
-
-      /* build the libname */
-      snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
-               cipher->module);
-      sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
-
-      alg_name = strdup(cipher->name);
-      if (strchr(alg_name, '-'))
-       *strchr(alg_name, '-') = '\0';
-
-      if (silc_sim_load(sim)) {
-       cipher_obj.set_key =
-         silc_sim_getsym(sim, silc_sim_symname(alg_name,
-                                               SILC_CIPHER_SIM_SET_KEY));
-       SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
-       cipher_obj.set_key_with_string =
-         silc_sim_getsym(sim,
-           silc_sim_symname(alg_name,
-             SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
-       SILC_LOG_DEBUG(("set_key_with_string=%p",
-         cipher_obj.set_key_with_string));
-       cipher_obj.encrypt =
-         silc_sim_getsym(sim, silc_sim_symname(alg_name,
-                                               SILC_CIPHER_SIM_ENCRYPT_CBC));
-       SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
-        cipher_obj.decrypt =
-         silc_sim_getsym(sim, silc_sim_symname(alg_name,
-                                               SILC_CIPHER_SIM_DECRYPT_CBC));
-       SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
-        cipher_obj.context_len =
-         silc_sim_getsym(sim, silc_sim_symname(alg_name,
-                                               SILC_CIPHER_SIM_CONTEXT_LEN));
-       SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
-
-       /* Put the SIM to the list of all SIM's in server */
-       silc_dlist_add(server->sim, sim);
-
-       silc_free(alg_name);
-      } else {
-       SILC_LOG_ERROR(("Error configuring ciphers"));
-       silc_server_stop(server);
-       exit(1);
-      }
-
-      /* Register the cipher */
-      silc_cipher_register(&cipher_obj);
-#else
-      SILC_LOG_ERROR(("Dynamic module support not compiled, "
-                       "can't load modules!"));
-      silc_server_stop(server);
-      exit(1);
-#endif
     }
     cipher = cipher->next;
   } /* while */
@@ -1518,7 +1755,7 @@ bool silc_server_config_register_ciphers(SilcServer server)
 /* Registers configured hash functions. These can then be allocated by the
    server when needed. */
 
-bool silc_server_config_register_hashfuncs(SilcServer server)
+SilcBool silc_server_config_register_hashfuncs(SilcServer server)
 {
   SilcServerConfig config = server->config;
   SilcServerConfigHash *hash = config->hash;
@@ -1544,53 +1781,6 @@ bool silc_server_config_register_hashfuncs(SilcServer server)
        silc_server_stop(server);
        exit(1);
       }
-    } else {
-#ifdef SILC_SIM
-      /* Load (try at least) the hash SIM module */
-      SilcHashObject hash_obj;
-      SilcSim sim;
-
-      memset(&hash_obj, 0, sizeof(hash_obj));
-      hash_obj.name = hash->name;
-      hash_obj.block_len = hash->block_length;
-      hash_obj.hash_len = hash->digest_length;
-
-      sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
-
-      if ((silc_sim_load(sim))) {
-       hash_obj.init =
-         silc_sim_getsym(sim, silc_sim_symname(hash->name,
-                                               SILC_HASH_SIM_INIT));
-       SILC_LOG_DEBUG(("init=%p", hash_obj.init));
-       hash_obj.update =
-         silc_sim_getsym(sim, silc_sim_symname(hash->name,
-                                               SILC_HASH_SIM_UPDATE));
-       SILC_LOG_DEBUG(("update=%p", hash_obj.update));
-        hash_obj.final =
-         silc_sim_getsym(sim, silc_sim_symname(hash->name,
-                                               SILC_HASH_SIM_FINAL));
-       SILC_LOG_DEBUG(("final=%p", hash_obj.final));
-        hash_obj.context_len =
-         silc_sim_getsym(sim, silc_sim_symname(hash->name,
-                                               SILC_HASH_SIM_CONTEXT_LEN));
-       SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
-
-       /* Put the SIM to the table of all SIM's in server */
-       silc_dlist_add(server->sim, sim);
-      } else {
-       SILC_LOG_ERROR(("Error configuring hash functions"));
-       silc_server_stop(server);
-       exit(1);
-      }
-
-      /* Register the hash function */
-      silc_hash_register(&hash_obj);
-#else
-      SILC_LOG_ERROR(("Dynamic module support not compiled, "
-                       "can't load modules!"));
-      silc_server_stop(server);
-      exit(1);
-#endif
     }
     hash = hash->next;
   } /* while */
@@ -1601,7 +1791,7 @@ bool silc_server_config_register_hashfuncs(SilcServer server)
 /* Registers configure HMACs. These can then be allocated by the server
    when needed. */
 
-bool silc_server_config_register_hmacs(SilcServer server)
+SilcBool silc_server_config_register_hmacs(SilcServer server)
 {
   SilcServerConfig config = server->config;
   SilcServerConfigHmac *hmac = config->hmac;
@@ -1633,32 +1823,9 @@ bool silc_server_config_register_hmacs(SilcServer server)
 
 /* Registers configured PKCS's. */
 
-bool silc_server_config_register_pkcs(SilcServer server)
+SilcBool silc_server_config_register_pkcs(SilcServer server)
 {
-  SilcServerConfig config = server->config;
-  SilcServerConfigPkcs *pkcs = config->pkcs;
-
-  SILC_LOG_DEBUG(("Registering configured PKCS"));
-
-  if (!pkcs)
-    return FALSE;
-
-  while (pkcs) {
-    int i;
-    for (i = 0; silc_default_pkcs[i].name; i++)
-      if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
-       silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
-       break;
-      }
-    if (!silc_pkcs_is_supported(pkcs->name)) {
-      SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
-      silc_server_stop(server);
-      exit(1);
-    }
-    pkcs = pkcs->next;
-  } /* while */
-
-  return TRUE;
+  return FALSE;
 }
 
 /* Sets log files where log messages are saved by the server logger. */
@@ -1670,11 +1837,11 @@ void silc_server_config_setlogfiles(SilcServer server)
 
   SILC_LOG_DEBUG(("Setting configured log file names and options"));
 
-  silc_log_timestamp = config->logging_timestamp;
-  silc_log_quick = config->logging_quick;
-  silc_log_flushdelay = (config->logging_flushdelay ?
-                        config->logging_flushdelay :
-                        SILC_SERVER_LOG_FLUSH_DELAY);
+  silc_log_timestamp(config->logging_timestamp);
+  silc_log_quick(config->logging_quick);
+  silc_log_flushdelay(config->logging_flushdelay ?
+                     config->logging_flushdelay :
+                     SILC_SERVER_LOG_FLUSH_DELAY);
 
   if ((this = config->logging_fatals))
     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
@@ -1845,12 +2012,12 @@ silc_server_config_find_backup_conn(SilcServer server, char *host)
 /* Returns TRUE if configuration for a router connection that we are
    initiating exists. */
 
-bool silc_server_config_is_primary_route(SilcServer server)
+SilcBool silc_server_config_is_primary_route(SilcServer server)
 {
   SilcServerConfig config = server->config;
   SilcServerConfigRouter *serv = NULL;
   int i;
-  bool found = FALSE;
+  SilcBool found = FALSE;
 
   serv = config->routers;
   for (i = 0; serv; i++) {