Added the config directive PublicKeyDir for the client block.
authorGiovanni Giacobbi <johnny@silcnet.org>
Sat, 30 Nov 2002 13:26:26 +0000 (13:26 +0000)
committerGiovanni Giacobbi <johnny@silcnet.org>
Sat, 30 Nov 2002 13:26:26 +0000 (13:26 +0000)
Affected files doc/exampe_silcd.conf.in, silcd/serverconfig.[ch].

apps/silcd/serverconfig.c
doc/example_silcd.conf.in

index 73a38bfde43bba4a89a656b8cd95d75622496d76..a49a0844a7256612ecf01f44beb41d04a672e98f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "serverincludes.h"
 #include "server_internal.h"
+#include <dirent.h>
 
 #if 0
 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
@@ -118,7 +119,7 @@ my_find_param(SilcServerConfig config, const char *name)
 }
 
 /* parse an authdata according to its auth method */
-static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
+static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
                              void **auth_data, SilcUInt32 *auth_data_len)
 {
   if (auth_meth == SILC_AUTH_PASSWORD) {
@@ -138,6 +139,7 @@ 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;
+    SilcPublicKey cached_key;
 
     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)) {
@@ -146,6 +148,16 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
        return FALSE;
       }
 
+    if (*auth_data &&
+       silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key,
+                                NULL, silc_hash_public_key, NULL,
+                                silc_hash_public_key_compare, NULL)) {
+      silc_pkcs_public_key_free(public_key);
+      SILC_SERVER_LOG_WARNING(("Warning: file \"%s\" contains a double "
+                              "public key (key discarded)", p));
+      return TRUE; /* non fatal error */
+    }
+
     /* The auth_data is a pointer to the hash table of public keys. */
     if (auth_data) {
       if (*auth_data == NULL)
@@ -161,6 +173,46 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
   return TRUE;
 }
 
+static bool my_parse_publickeydir(const char *dirname, void **auth_data)
+{
+  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 FALSE;
+  }
+
+  /* errors are not considered fatal */
+  while ((get_file = readdir(dp))) {
+    int dirname_len = strlen(dirname);
+    char buf[1023];
+    const char *filename = get_file->d_name;
+    struct stat check_file;
+
+    if (!strcmp(filename, ".") || !strcmp(filename, ".."))
+      continue;
+
+    snprintf(buf, sizeof(buf) - 2, "%s%s%s", dirname,
+            (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
+    buf[sizeof(buf) - 1] = 0;
+
+    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)) {
+      my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
+      total++;
+    }
+  }
+
+  SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
+  return TRUE;
+}
+
 /* Callbacks */
 
 SILC_CONFIG_CALLBACK(fetch_generic)
@@ -521,6 +573,7 @@ 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,
@@ -533,6 +586,7 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   }
   else if (!strcmp(name, "privatekey")) {
     char *file_tmp = (char *) val;
+    CONFIG_IS_DOUBLE(server_info->private_key);
 
     /* try to load specified file, if fail stop config parsing */
     if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
@@ -752,6 +806,12 @@ SILC_CONFIG_CALLBACK(fetch_client)
       goto got_err;
     }
   }
+  else if (!strcmp(name, "publickeydir")) {
+    if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
+      got_errno = SILC_CONFIG_EPRINTLINE;
+      goto got_err;
+    }
+  }
   else if (!strcmp(name, "params")) {
     CONFIG_IS_DOUBLE(tmp->param);
     tmp->param = my_find_param(config, (char *) val);
@@ -812,13 +872,18 @@ SILC_CONFIG_CALLBACK(fetch_admin)
     }
   }
   else if (!strcmp(name, "publickey")) {
-    CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
                           (void **)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
   }
+  else if (!strcmp(name, "publickeydir")) {
+    if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
+      got_errno = SILC_CONFIG_EPRINTLINE;
+      goto got_err;
+    }
+  }
   else
     return SILC_CONFIG_EINTERNAL;
   return SILC_CONFIG_OK;
@@ -1158,6 +1223,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 }
 };
@@ -1168,6 +1234,7 @@ static const SilcConfigTable table_admin[] = {
   { "nick",            SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
   { "passphrase",      SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
   { "publickey",       SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
+  { "publickeydir",    SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
   { "port",            SILC_CONFIG_ARG_INT,    fetch_admin,    NULL },
   { "params",          SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
   { 0, 0, 0, 0 }
index f6e7839ab62528ea71cfd0bb5d07e8dbe272680c..25d05a3a4db7027ae259aadcf8a1a0ce0ac3b710 100644 (file)
@@ -405,10 +405,9 @@ ConnectionParams {
 #
 # The authentication data is specified by Passphrase and/or PublicKey.
 # If both are provided then both password and public key based authentication
-# is allowed.  If the Publickey is used it includes the file path to the
-# public key file.  If none of them is provided then authentication is not
-# required.  The PublicKey can be set multiple times to set multiple
-# public keys for one connection.
+# is allowed.  The "PublicKey" includes the single key contained in the
+# specified file, while "PublicKeyDir" includes all files in the specified
+# directory, which must all be valid public keys, non recursively.
 #
 # Next example connection will match to all incoming client connections,
 # and no authentication is required.
@@ -419,6 +418,7 @@ Client {
        #PublicKey = "/path/to/the/user_my.key";
        #PublicKey = "/path/to/the/user_221.key";
        #PublicKey = "/path/to/the/user_313.key";
+       #PublicKeyDir = "/path/to/keys/dir";
        Params = "normal";
 };