Merged silc_1_0_branch to trunk.
[silc.git] / apps / silcd / serverconfig.c
index 911caff0dde735085b13ccc4fa628097740cbe6e..8ff643c1e0f4fc126349a05cdba23d956d3ec844 100644 (file)
@@ -2,7 +2,7 @@
 
   serverconfig.c
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
@@ -303,6 +303,10 @@ SILC_CONFIG_CALLBACK(fetch_generic)
   else if (!strcmp(name, "qos_limit_usec")) {
     config->param.qos_limit_usec = *(SilcUInt32 *)val;
   }
+  else if (!strcmp(name, "debug_string")) {
+    CONFIG_IS_DOUBLE(config->debug_string);
+    config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
+  }
   else
     return SILC_CONFIG_EINTERNAL;
 
@@ -460,7 +464,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) {
@@ -495,22 +499,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;
@@ -576,7 +598,7 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
     char *file_tmp = (char *) val;
     CONFIG_IS_DOUBLE(server_info->public_key);
 
-    /* try to load specified file, if fail stop config parsing */
+    /* 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,
@@ -586,10 +608,21 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
       }
   }
   else if (!strcmp(name, "privatekey")) {
+    struct stat st;
     char *file_tmp = (char *) val;
     CONFIG_IS_DOUBLE(server_info->private_key);
 
-    /* try to load specified file, if fail stop config parsing */
+    /* Check the private key file permissions. */
+    if ((stat(file_tmp, &st)) != -1) {
+      if ((st.st_mode & 0777) != 0600) {
+       SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
+                             "file \"%s\".  The permissions must be "
+                             "0600.", file_tmp));
+        return SILC_CONFIG_ESILENT;
+      }
+    }
+
+    /* Try to load specified file, if fail stop config parsing */
     if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
                                    "", 0, SILC_PKCS_FILE_BIN))
       if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
@@ -603,9 +636,13 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   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;
 }
 
@@ -951,6 +988,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);
@@ -1014,6 +1055,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;
@@ -1124,6 +1169,7 @@ static const SilcConfigTable table_general[] = {
   { "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 },
+  { "debug_string",                    SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
   { 0, 0, 0, 0 }
 };
 
@@ -1438,6 +1484,7 @@ SilcServerConfig silc_server_config_alloc(const char *filename)
       }
     }
     silc_server_config_destroy(config_new);
+    silc_config_close(file);
     return NULL;
   }
 
@@ -1495,6 +1542,7 @@ void silc_server_config_destroy(SilcServerConfig config)
 
   /* 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);