Added support for multiple PublicKey instances in the config
authorPekka Riikonen <priikone@silcnet.org>
Tue, 12 Mar 2002 17:31:30 +0000 (17:31 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 12 Mar 2002 17:31:30 +0000 (17:31 +0000)
file.

14 files changed:
CHANGES
TODO
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/protocol.c
apps/silcd/server.c
apps/silcd/server_internal.h
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
doc/example_silcd.conf.in
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index f3d99036d65d2bb4a92c512e84d16b7a9d97a252..82b8c68dfa359de2eeed9b43d23ac59a3fb5e36a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,24 @@
+Tue Mar 12 17:58:59 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_hash_public_key and silc_hash_public_key_compare
+         functions to be used with SilcHashTable.  They can be used to
+         hash public keys and compare public keys in hash table.  Affected
+         file lib/silcutil/silcutil.[ch].
+
+       * Added support for specifying multiple public keys for Client
+         connection section in server configuration file.  This makes it
+         possible to accept multiple public keys from same host, or to
+         make a section that accepts any incoming host, and have the
+         accepted public keys listed in the section.
+
+         Added functions silc_sever_[find/get]_public_key,  added the
+         support for this actually to all connection sections but only
+         the Client section is currently allowed to specify multiple
+         public keys.
+
+         Affected files are silcd/server.c, server_internal.h,
+         command.c, protocol.c, server_util.[ch], packet_receive.c.
+
 Mon Mar 11 23:37:38 EET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Merged Irssi 0.8.2 from irssi.org CVS.
diff --git a/TODO b/TODO
index d32f8bf141803cbe57d0ccbd530f13139a37fd1f..322e71f0792fc5dee65317a83331b397127010e0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -37,10 +37,6 @@ TODO/bugs In SILC Server
 
  o Configuration file additions:
 
-       o Add support for multipe PublicKey params in connections 
-         sections.  For now, add this support only in Client and not
-         in ServerConnection nor RouterConnection.
-
        o Add version handling, to allow, disallow certain versions to
          connect.
 
index 02ec6d1d6aefaf07681f48562db78c15108bf5f7..baddfb1896bb9c82aed0ac3168d8c6aa2829787d 100644 (file)
@@ -4583,6 +4583,7 @@ SILC_SERVER_CMD_FUNC(oper)
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
   bool result = FALSE;
+  SilcPublicKey cached_key;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
 
@@ -4624,10 +4625,14 @@ SILC_SERVER_CMD_FUNC(oper)
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
-  if (!result && admin->publickey)
+  if (!result && admin->publickeys) {
+    cached_key = silc_server_get_public_key(server, admin->publickeys);
+    if (!cached_key)
+      goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
-                                  admin->publickey, 0,
-                                  idata->hash, client->id, SILC_ID_CLIENT);
+                                  cached_key, 0, idata->hash, 
+                                  client->id, SILC_ID_CLIENT);
+  }
   if (!result) {
     /* Authentication failed */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
@@ -4670,6 +4675,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
   bool result = FALSE;
+  SilcPublicKey cached_key;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
 
@@ -4717,10 +4723,14 @@ SILC_SERVER_CMD_FUNC(silcoper)
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
-  if (!result && admin->publickey)
+  if (!result && admin->publickeys) {
+    cached_key = silc_server_get_public_key(server, admin->publickeys);
+    if (!cached_key)
+      goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
-                                  admin->publickey, 0,
-                                  idata->hash, client->id, SILC_ID_CLIENT);
+                                  cached_key, 0, idata->hash, 
+                                  client->id, SILC_ID_CLIENT);
+  }
   if (!result) {
     /* Authentication failed */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
index 1c817358a4d4f02b710d7de50876c88976258fcc..1bc8b853832deea7b0ee4ea27b390aa7e7143442 100644 (file)
@@ -2535,11 +2535,11 @@ void silc_server_connection_auth_request(SilcServer server,
     client = silc_server_config_find_client(server, sock->hostname);
   if (client) {
     if (client->passphrase) {
-      if (client->publickey && !server->config->prefer_passphrase_auth)
+      if (client->publickeys && !server->config->prefer_passphrase_auth)
        auth_meth = SILC_AUTH_PUBLIC_KEY;
       else
        auth_meth = SILC_AUTH_PASSWORD;
-    } else if (client->publickey)
+    } else if (client->publickeys)
       auth_meth = SILC_AUTH_PUBLIC_KEY;
   }
 
index a33184d7b1e9d2087afcc8c3e04b80f3b25b792b..2200bfb8ccdad5cca50d4f4473bf0adf8be9c7c8 100644 (file)
@@ -407,9 +407,7 @@ static void silc_server_protocol_ke_continue(SilcSKE ske, void *context)
   if (ske->status != SILC_SKE_STATUS_OK) {
     SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol",
                    silc_ske_map_status(ske->status)));
-    SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol",
-                   silc_ske_map_status(ske->status)));
-    
+
     protocol->state = SILC_PROTOCOL_STATE_ERROR;
     silc_protocol_execute(protocol, server->schedule, 0, 300000);
     return;
@@ -495,8 +493,6 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       if (status != SILC_SKE_STATUS_OK) {
        SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol",
                        silc_ske_map_status(status)));
-       SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol",
-                       silc_ske_map_status(status)));
 
        protocol->state = SILC_PROTOCOL_STATE_ERROR;
        silc_protocol_execute(protocol, server->schedule, 0, 300000);
@@ -532,8 +528,6 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       if (status != SILC_SKE_STATUS_OK) {
        SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol",
                        silc_ske_map_status(status)));
-       SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol",
-                       silc_ske_map_status(status)));
 
        protocol->state = SILC_PROTOCOL_STATE_ERROR;
        silc_protocol_execute(protocol, server->schedule, 0, 300000);
@@ -575,8 +569,6 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       if (status != SILC_SKE_STATUS_OK) {
        SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol",
                        silc_ske_map_status(status)));
-       SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol",
-                       silc_ske_map_status(status)));
 
        protocol->state = SILC_PROTOCOL_STATE_ERROR;
        silc_protocol_execute(protocol, server->schedule, 0, 300000);
@@ -613,8 +605,6 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       if (status != SILC_SKE_STATUS_OK) {
        SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol",
                        silc_ske_map_status(status)));
-       SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol",
-                       silc_ske_map_status(status)));
 
        protocol->state = SILC_PROTOCOL_STATE_ERROR;
        silc_protocol_execute(protocol, server->schedule, 0, 300000);
@@ -827,7 +817,7 @@ silc_server_get_public_key_auth(SilcServer server,
 static bool 
 silc_server_get_authentication(SilcServerConnAuthInternalContext *ctx,
                               char *local_passphrase,
-                              void *local_publickey,
+                              SilcHashTable local_publickeys,
                               unsigned char *remote_auth,
                               SilcUInt32 remote_auth_len)
 {
@@ -837,7 +827,8 @@ silc_server_get_authentication(SilcServerConnAuthInternalContext *ctx,
 
   /* If we don't have authentication data set at all we do not require
      authentication at all */
-  if (!local_passphrase && !local_publickey) {
+  if (!local_passphrase && (!local_publickeys || 
+                           !silc_hash_table_count(local_publickeys))) {
     SILC_LOG_DEBUG(("No authentication required"));
     return TRUE;
   }
@@ -854,13 +845,22 @@ silc_server_get_authentication(SilcServerConnAuthInternalContext *ctx,
   }
 
   /* Try public key authenetication */
-  if (!result && local_publickey) {
+  if (!result && local_publickeys) {
+    SilcPublicKey cached_key;
+    SilcPublicKey remote_key = 
+      ((SilcIDListData)ctx->sock->user_data)->public_key;
+
     SILC_LOG_DEBUG(("Public key authentication"));
-    result = silc_server_public_key_authentication(server, 
-                                                  local_publickey,
+
+    /* Find the public key to be used in authentication */
+    cached_key = silc_server_find_public_key(server, local_publickeys,
+                                            remote_key);
+    if (!cached_key)
+      return FALSE;
+
+    result = silc_server_public_key_authentication(server, cached_key,
                                                   remote_auth,
-                                                  remote_auth_len, 
-                                                  ske);
+                                                  remote_auth_len, ske);
   }
 
   return result;
@@ -963,19 +963,17 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
          
          if (client) {
            ret = silc_server_get_authentication(ctx, client->passphrase,
-                                                client->publickey,
+                                                client->publickeys,
                                                 auth_data, payload_len);
            if (!ret) {
              /* Authentication failed */
              SILC_LOG_ERROR(("Authentication failed"));
-             SILC_LOG_DEBUG(("Authentication failed"));
              silc_free(auth_data);
              protocol->state = SILC_PROTOCOL_STATE_ERROR;
              silc_protocol_execute(protocol, server->schedule, 0, 300000);
              return;
            }
          } else {
-           SILC_LOG_DEBUG(("No configuration for remote client connection"));
            SILC_LOG_ERROR(("Remote client connection not configured"));
            SILC_LOG_ERROR(("Authentication failed"));
            silc_free(auth_data);
@@ -992,19 +990,17 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
          
          if (serv) {
            ret = silc_server_get_authentication(ctx, serv->passphrase,
-                                                serv->publickey,
+                                                serv->publickeys,
                                                 auth_data, payload_len);
            if (!ret) {
              /* Authentication failed */
              SILC_LOG_ERROR(("Authentication failed"));
-             SILC_LOG_DEBUG(("Authentication failed"));
              silc_free(auth_data);
              protocol->state = SILC_PROTOCOL_STATE_ERROR;
              silc_protocol_execute(protocol, server->schedule, 0, 300000);
              return;
            }
          } else {
-           SILC_LOG_DEBUG(("No configuration for remote server connection"));
            SILC_LOG_ERROR(("Remote server connection not configured"));
            SILC_LOG_ERROR(("Authentication failed"));
            protocol->state = SILC_PROTOCOL_STATE_ERROR;
@@ -1021,19 +1017,17 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
 
          if (serv) {
            ret = silc_server_get_authentication(ctx, serv->passphrase,
-                                                serv->publickey,
+                                                serv->publickeys,
                                                 auth_data, payload_len);
            if (!ret) {
              /* Authentication failed */
              SILC_LOG_ERROR(("Authentication failed"));
-             SILC_LOG_DEBUG(("Authentication failed"));
              silc_free(auth_data);
              protocol->state = SILC_PROTOCOL_STATE_ERROR;
              silc_protocol_execute(protocol, server->schedule, 0, 300000);
              return;
            }
          } else {
-           SILC_LOG_DEBUG(("No configuration for remote router connection"));
            SILC_LOG_ERROR(("Remote router connection not configured"));
            SILC_LOG_ERROR(("Authentication failed"));
            silc_free(auth_data);
index b9a09d99d4e4dcb830caee5c2e335dd6e5a1aebf..1f468f1dac29103a9450488c7af211a98e8f44c5 100644 (file)
@@ -765,20 +765,18 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     conn = sconn->conn;
 
   if (conn) {
-    /* Match found. Use the configured authentication method */
+    /* Match found. Use the configured authentication method. Take only
+       the passphrase, since for public key auth we automatically use
+       our local key pair. */
     if (conn->passphrase) {
-      if (conn->publickey && !server->config->prefer_passphrase_auth) {
-       proto_ctx->auth_data = conn->publickey;
-       proto_ctx->auth_data_len = 0;
+      if (conn->publickeys && !server->config->prefer_passphrase_auth) {
        proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
       } else {
        proto_ctx->auth_data = strdup(conn->passphrase);
        proto_ctx->auth_data_len = strlen(conn->passphrase);
        proto_ctx->auth_meth = SILC_AUTH_PASSWORD;
       }
-    } else if (conn->publickey) {
-      proto_ctx->auth_data = conn->publickey;
-      proto_ctx->auth_data_len = 0;
+    } else if (conn->publickeys) {
       proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
     } else {
       proto_ctx->auth_meth = SILC_AUTH_NONE;
index d35c5d8a09f3e60530ec30121c5d39d9c9eb3aae..b0d38cb1473604d776f351462d8de85d0c6f00c1 100644 (file)
@@ -179,7 +179,7 @@ do {                                                \
   if ((x)) {                                           \
     if ((x)->param && (x)->param->key_exchange_pfs)    \
       (p)->flags |= SILC_SKE_SP_FLAG_PFS;              \
-    if (!(x)->publickey                              \
+    if (!(x)->publickeys)                              \
       (p)->flags |= SILC_SKE_SP_FLAG_MUTUAL;           \
   }
 
index 4425e64dc5cdd96f4552b26c5af7692261205fad..dc76c48161f642ac13932a06fc0148f71bbe463e 100644 (file)
@@ -46,7 +46,7 @@ static void silc_server_remove_clients_channels(SilcServer server,
   /* Remove the client from all channels. The client is removed from
      the channels' user list. */
   silc_hash_table_list(client->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
     channel = chl->channel;
 
     /* Remove channel from client's channel list */
@@ -101,7 +101,7 @@ static void silc_server_remove_clients_channels(SilcServer server,
        channel->disabled = TRUE;
 
        silc_hash_table_list(channel->user_list, &htl2);
-       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
+       while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
          silc_hash_table_del(chl2->client->channels, channel);
          silc_hash_table_del(channel->user_list, chl2->client);
          channel->user_count--;
@@ -343,7 +343,7 @@ bool silc_server_remove_clients_by_server(SilcServer server,
      this server's client(s) on the channel. As they left the channel we
      must re-generate the channel key. */
   silc_hash_table_list(channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
+  while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
     if (!silc_server_create_channel_key(server, channel, 0)) {
       silc_hash_table_list_reset(&htl);
       silc_hash_table_free(channels);
@@ -706,7 +706,7 @@ bool silc_server_channel_has_global(SilcChannelEntry channel)
   SilcHashTableList htl;
 
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
     if (chl->client->router) {
       silc_hash_table_list_reset(&htl);
       return TRUE;
@@ -726,7 +726,7 @@ bool silc_server_channel_has_local(SilcChannelEntry channel)
   SilcHashTableList htl;
 
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
     if (!chl->client->router) {
       silc_hash_table_list_reset(&htl);
       return TRUE;
@@ -806,3 +806,53 @@ SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
 
   return count;
 }
+
+/* Finds locally cached public key by the public key received in the SKE. 
+   If we have it locally cached then we trust it and will use it in the
+   authentication protocol.  Returns the locally cached public key or NULL
+   if we do not find the public key.  */
+
+SilcPublicKey silc_server_find_public_key(SilcServer server, 
+                                         SilcHashTable local_public_keys,
+                                         SilcPublicKey remote_public_key)
+{
+  SilcPublicKey cached_key;
+
+  SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
+                 silc_hash_table_count(local_public_keys)));
+
+  if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
+                               (void **)&cached_key, NULL, 
+                               silc_hash_public_key, NULL,
+                               silc_hash_public_key_compare, NULL)) {
+    SILC_LOG_ERROR(("Public key not found"));
+    return NULL;
+  }
+
+  SILC_LOG_DEBUG(("Found public key"));
+
+  return cached_key;
+}
+
+/* This returns the first public key from the table of public keys.  This
+   is used only in cases where single public key exists in the table and
+   we want to get a pointer to it.  For public key tables that has multiple
+   keys in it the silc_server_find_public_key must be used. */
+
+SilcPublicKey silc_server_get_public_key(SilcServer server,
+                                        SilcHashTable local_public_keys)
+{
+  SilcPublicKey cached_key;
+  SilcHashTableList htl;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  assert(silc_hash_table_count(local_public_keys) < 2);
+
+  silc_hash_table_list(local_public_keys, &htl);
+  if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
+    return NULL;
+  silc_hash_table_list_reset(&htl);
+
+  return cached_key;
+}
index 83cd26bd8e055650d8e7480c9da7dea538fbda89..ca54b1b8614851b5316d44445838c8a52de0f1c8 100644 (file)
@@ -86,4 +86,19 @@ char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len);
 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
                                         SilcSocketType type);
 
+/* Finds locally cached public key by the public key received in the SKE. 
+   If we have it locally cached then we trust it and will use it in the
+   authentication protocol.  Returns the locally cached public key or NULL
+   if we do not find the public key.  */
+SilcPublicKey silc_server_find_public_key(SilcServer server, 
+                                         SilcHashTable local_public_keys,
+                                         SilcPublicKey remote_public_key);
+
+/* This returns the first public key from the table of public keys.  This
+   is used only in cases where single public key exists in the table and
+   we want to get a pointer to it.  For public key tables that has multiple
+   keys in it the silc_server_find_public_key must be used. */
+SilcPublicKey silc_server_get_public_key(SilcServer server,
+                                        SilcHashTable local_public_keys);
+
 #endif /* SERVER_UTIL_H */
index e0f029158c047c847673f8231f2b85b6597198ee..0a0bfe55ee4762a35aefc556d1f6a281d52f0706 100644 (file)
 
 /* Free the authentication fields in the specified struct
  * Expands to two instructions */
-#define CONFIG_FREE_AUTH(__section__)                                  \
-  silc_free(__section__->passphrase);                                  \
-  silc_pkcs_public_key_free(__section__->publickey)
+#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);
+}
 
 /* Set default values to those parameters that have not been defined */
 static void 
@@ -106,8 +112,9 @@ my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line)
 }
 
 /* parse an authdata according to its auth method */
-static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, SilcUInt32 line,
-                             void **auth_data, SilcUInt32 *auth_data_len)
+static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, 
+                             SilcUInt32 line, void **auth_data, 
+                             SilcUInt32 *auth_data_len)
 {
   if (auth_meth == SILC_AUTH_PASSWORD) {
     /* p is a plain text password */
@@ -116,7 +123,7 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, SilcUInt32 line
     if (auth_data_len)
       *auth_data_len = (SilcUInt32) strlen(p);
   } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
-    /* p is a public key */
+    /* p is a public key file name */
     SilcPublicKey public_key;
 
     if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
@@ -125,10 +132,16 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, SilcUInt32 line
                "Could not load public key file!\n", line);
        return FALSE;
       }
-    if (auth_data)
-      *auth_data = (void *) public_key;
-    if (auth_data_len)
-      *auth_data_len = 0;
+
+    /* 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);
+    }
   } else {
     fprintf(stderr, "\nError while parsing config file at line %lu: "
            "Unknown authentication method.\n", line);
@@ -651,6 +664,7 @@ SILC_CONFIG_CALLBACK(fetch_client)
     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
   }
   else if (!strcmp(name, "passphrase")) {
+    CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
                           (void **)&tmp->passphrase,
                           &tmp->passphrase_len)) {
@@ -660,7 +674,7 @@ SILC_CONFIG_CALLBACK(fetch_client)
   }
   else if (!strcmp(name, "publickey")) {
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
-                          &tmp->publickey, NULL)) {
+                          (void **)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_ESILENT;
       goto got_err;
     }
@@ -722,6 +736,7 @@ SILC_CONFIG_CALLBACK(fetch_admin)
     tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
   }
   else if (!strcmp(name, "passphrase")) {
+    CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
                           (void **)&tmp->passphrase,
                           &tmp->passphrase_len)) {
@@ -730,8 +745,9 @@ 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, line,
-                          &tmp->publickey, NULL)) {
+                          (void **)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_ESILENT;
       goto got_err;
     }
@@ -825,6 +841,7 @@ SILC_CONFIG_CALLBACK(fetch_server)
     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
   }
   else if (!strcmp(name, "passphrase")) {
+    CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
                           (void **)&tmp->passphrase,
                           &tmp->passphrase_len)) {
@@ -833,8 +850,9 @@ 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, line,
-                          &tmp->publickey, NULL)) {
+                          (void **)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_ESILENT;
       goto got_err;
     }
@@ -905,6 +923,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
     tmp->port = (SilcUInt16) port;
   }
   else if (!strcmp(name, "passphrase")) {
+    CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
                           (void **)&tmp->passphrase,
                           &tmp->passphrase_len)) {
@@ -913,8 +932,9 @@ 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, line,
-                          &tmp->publickey, NULL)) {
+                          (void **)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_ESILENT;
       goto got_err;
     }
index c4190e36dffcfc070d4c1b8a6ee7baa99a13c50e..2af85bbd8618fffb7ed540cfd335dd213d5a7f96 100644 (file)
@@ -90,7 +90,7 @@ typedef struct SilcServerConfigClientStruct {
   char *host;
   unsigned char *passphrase;
   SilcUInt32 passphrase_len;
-  void *publickey;
+  SilcHashTable publickeys;
   SilcServerConfigConnParams *param;
   struct SilcServerConfigClientStruct *next;
 } SilcServerConfigClient;
@@ -102,7 +102,7 @@ typedef struct SilcServerConfigAdminStruct {
   char *nick;
   unsigned char *passphrase;
   SilcUInt32 passphrase_len;
-  void *publickey;
+  SilcHashTable publickeys;
   struct SilcServerConfigAdminStruct *next;
 } SilcServerConfigAdmin;
 
@@ -118,7 +118,7 @@ typedef struct SilcServerConfigServerStruct {
   char *host;
   unsigned char *passphrase;
   SilcUInt32 passphrase_len;
-  void *publickey;
+  SilcHashTable publickeys;
   char *version;
   SilcServerConfigConnParams *param;
   bool backup_router;
@@ -130,7 +130,7 @@ typedef struct SilcServerConfigRouterStruct {
   char *host;
   unsigned char *passphrase;
   SilcUInt32 passphrase_len;
-  void *publickey;
+  SilcHashTable publickeys;
   SilcUInt16 port;
   char *version;
   SilcServerConfigConnParams *param;
index 5bac8bcc20fc049224656e881f01dc320a02c75e..2612c2197333cdcd332f74a13afb4ba5c85d1a9d 100644 (file)
@@ -298,11 +298,12 @@ ConnectionParams {
 # "param" is optional and can be used to set specific connection parameters
 # for this connection.
 #
-# The authentication data is specified by Passphrase and/or Publickey.
+# 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.
+# required.  The PublicKey can be set multiple times to set multiple 
+# public keys for one connection.
 #
 # Next example connection will match to all incoming client connections,
 # and no authentication is required.
@@ -310,7 +311,9 @@ ConnectionParams {
 Client {
        #Host = "10.1.*";
        #Passphrase = "secret";
-       #PublicKey = "/path/to/the/public.key";
+       #PublicKey = "/path/to/the/user_my.key";
+       #PublicKey = "/path/to/the/user_221.key";
+       #PublicKey = "/path/to/the/user_313.key";
        Params = "normal";
 };
 
@@ -320,9 +323,9 @@ Client {
 # The fields "Host", "User", and "Nick", are optional but you are encouraged
 # in using them to better identify your admins.
 #
-# The authentication data is specified by Passphrase and/or Publickey.
+# 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
+# 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.
 #
@@ -331,7 +334,7 @@ Admin {
        User = "priikone";
        Nick = "pekka";
        Passphrase = "verysecret";
-       # Publickey = "/path/to/the/public.key";
+       # PublicKey = "/path/to/the/public.key";
 };
 
 #
@@ -342,9 +345,9 @@ Admin {
 # Thus, if this server is not router do not configure this section.  If
 # your server is router, this must be configured.
 #
-# The authentication data is specified by Passphrase and/or Publickey.
+# 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
+# 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.
 #
@@ -355,7 +358,7 @@ Admin {
 ServerConnection {
        Host = "10.2.1.7";
        Passphrase = "verysecret";
-       #Publickey = "/path/to/the/public.key";
+       #PublicKey = "/path/to/the/public.key";
        Params = "normal";
        Backup = false;
 };
@@ -368,9 +371,9 @@ ServerConnection {
 # this section includes all configured router connections.  The first
 # configured connection is the primary route.
 #
-# The authentication data is specified by Passphrase and/or Publickey.
+# 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
+# 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.
 #
@@ -389,7 +392,7 @@ RouterConnection {
        Host = "10.2.1.100";
        Port = 706;
        Passphrase = "verysecret";
-       #Publickey = "/path/to/the/public.key";
+       #PublicKey = "/path/to/the/public.key";
        Params = "normal";
        Initiator = true;
        #BackupHost = "10.2.1.6";
index c3af592539a49d72b430f572c80cea7b40e4b307..ee7f2eea49d3aba9ac1c66984025809c60736bc4 100644 (file)
@@ -654,6 +654,16 @@ SilcUInt32 silc_hash_data(void *key, void *user_context)
   return h;
 }
 
+/* Hashed SILC Public key. */
+
+SilcUInt32 silc_hash_public_key(void *key, void *user_context)
+{
+  SilcPublicKey pk = (SilcPublicKey)key;
+  return (pk->len + silc_hash_string(pk->name, NULL) +
+         silc_hash_string(pk->identifier, NULL) +
+         silc_hash_data(pk->pk, (void *)pk->pk_len));
+}
+
 /* Compares two strings. May be used as SilcHashTable comparison function. */
 
 bool silc_hash_string_compare(void *key1, void *key2, void *user_context)
@@ -688,6 +698,14 @@ bool silc_hash_data_compare(void *key1, void *key2, void *user_context)
   return !memcmp(key1, key2, len);
 }
 
+/* Compares two SILC Public keys. May be used as SilcHashTable comparison
+   function. */
+
+bool silc_hash_public_key_compare(void *key1, void *key2, void *user_context)
+{
+  return silc_pkcs_public_key_compare(key1, key2);
+}
+
 /* Parses mode mask and returns the mode as string. */
 
 char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
index ca34315a7ea53e4ad44ed9d7b01f390f356fdcee..2f79f2600f197f48f1f61239ae39ad2431c91afa 100644 (file)
@@ -49,11 +49,14 @@ SilcUInt32 silc_hash_uint(void *key, void *user_context);
 SilcUInt32 silc_hash_ptr(void *key, void *user_context);
 SilcUInt32 silc_hash_id(void *key, void *user_context);
 SilcUInt32 silc_hash_data(void *key, void *user_context);
+SilcUInt32 silc_hash_public_key(void *key, void *user_context);
 bool silc_hash_string_compare(void *key1, void *key2, void *user_context);
 bool silc_hash_id_compare(void *key1, void *key2, void *user_context);
 bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context);
 bool silc_hash_data_compare(void *key1, void *key2, void *user_context);
-char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac);
+bool silc_hash_public_key_compare(void *key1, void *key2, void *user_context);
+char *silc_client_chmode(SilcUInt32 mode, const char *cipher, 
+                        const char *hmac);
 char *silc_client_chumode(SilcUInt32 mode);
 char *silc_client_chumode_char(SilcUInt32 mode);
 int silc_gettimeofday(struct timeval *p);