From bf4ccf6a5c7d6eae56f4d7d25fdd747dfcb5bb2c Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 23 Feb 2004 08:31:39 +0000 Subject: [PATCH] Added support for watching by public keys. --- CHANGES | 6 +++ apps/silcd/command.c | 95 ++++++++++++++++++++++++++++++++++-- apps/silcd/server.c | 9 +++- apps/silcd/server_internal.h | 1 + apps/silcd/server_util.c | 15 ++++-- 5 files changed, 118 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 61a90f08..81c054dc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Mon Feb 23 09:30:30 CET 2004 Pekka Riikonen + + * Added support for public key watching in server. Affected + files are silcd/server.c, server_internal.h, command.c, + server_util.c. + Sun Feb 22 19:03:59 EET 2004 Pekka Riikonen * Added public key to the SIlcClientEntry. Affected files diff --git a/apps/silcd/command.c b/apps/silcd/command.c index bb56e807..8adf8bf0 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -4007,9 +4007,9 @@ SILC_SERVER_CMD_FUNC(watch) SilcServerCommandContext cmd = (SilcServerCommandContext)context; SilcServer server = cmd->server; char *add_nick, *del_nick; - SilcUInt32 add_nick_len, del_nick_len, tmp_len; + SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len; char nick[128 + 1]; - unsigned char hash[16], *tmp; + unsigned char hash[16], *tmp, *pk; SilcClientEntry client; SilcClientID *client_id = NULL; @@ -4081,10 +4081,13 @@ SILC_SERVER_CMD_FUNC(watch) goto out; } + /* Take public key for watching by public key */ + pk = silc_argument_get_arg_type(cmd->args, 3, &pk_len); + /* Take nickname */ add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len); del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len); - if (!add_nick && !del_nick) { + if (!add_nick && !del_nick && !pk) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0); @@ -4162,6 +4165,92 @@ SILC_SERVER_CMD_FUNC(watch) silc_free(tmp); } + /* Add/del public key */ + if (pk) { + SilcUInt16 pkargc; + SilcArgumentPayload pkargs; + SilcUInt32 type; + SilcPublicKey public_key, pkkey; + + if (pk_len < 2) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, + 0); + goto out; + } + + /* Get the argument from the Argument List Payload */ + SILC_GET16_MSB(pkargc, pk); + pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc); + if (!pkargs) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, + 0); + goto out; + } + + pk = silc_argument_get_next_arg(pkargs, &type, &pk_len); + while (pk) { + if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key)) + continue; + if (type == 0x03) + type = 0x00; + + if (type == 0x00) { + /* Add public key to watch list */ + + /* Check whether this client is already watching this public key */ + if (silc_hash_table_find_by_context(server->watcher_list_pk, + public_key, client, NULL)) { + silc_pkcs_public_key_free(public_key); + silc_server_command_send_status_reply( + cmd, SILC_COMMAND_WATCH, + SILC_STATUS_ERR_NICKNAME_IN_USE, 0); + goto out; + } + + /* Get the public key from the watcher list and use the same key in + new entries as well. If key doesn't exist then create it. */ + pkkey = NULL; + if (!silc_hash_table_find(server->watcher_list_pk, public_key, + (void *)&pkkey, NULL)) + pkkey = public_key; + else + silc_pkcs_public_key_free(public_key); + + /* Add the client to the watcher list with the specified public + key. */ + silc_hash_table_add(server->watcher_list, public_key, client); + + } else if (type == 0x01) { + /* Delete public key from watch list */ + + /* Check that this client is watching this public key */ + if (silc_hash_table_find_by_context(server->watcher_list_pk, + public_key, client, + (void *)&pkkey)) { + silc_pkcs_public_key_free(public_key); + silc_server_command_send_status_reply( + cmd, SILC_COMMAND_WATCH, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0); + goto out; + } + + /* Delete the public key from the watcher list. */ + silc_hash_table_del_by_context(server->watcher_list_pk, + public_key, client); + + /* Now check whether there still exists entries with this key, if + not then free the key to not leak memory. */ + if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL)) + silc_pkcs_public_key_free(pkkey); + silc_pkcs_public_key_free(public_key); + } + + pk = silc_argument_get_next_arg(pkargs, &type, &pk_len); + } + } + /* Distribute the watch list to backup routers too */ if (server->backup) { SilcBuffer tmpbuf; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index afb0cb1f..083206bc 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -180,6 +180,7 @@ void silc_server_free(SilcServer server) silc_idcache_free(server->global_list->servers); silc_idcache_free(server->global_list->channels); silc_hash_table_free(server->watcher_list); + silc_hash_table_free(server->watcher_list_pk); silc_hash_free(server->md5hash); silc_hash_free(server->sha1hash); @@ -353,13 +354,19 @@ bool silc_server_init(SilcServer server) server->global_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); server->global_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); - /* Init watcher list */ + /* Init watcher lists */ server->watcher_list = silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL, silc_hash_data_compare, (void *)CLIENTID_HASH_LEN, NULL, NULL, TRUE); if (!server->watcher_list) goto err; + server->watcher_list_pk = + silc_hash_table_alloc(1, silc_hash_public_key, NULL, + silc_hash_public_key_compare, NULL, + NULL, NULL, TRUE); + if (!server->watcher_list_pk) + goto err; /* Init public key list */ server->pk_hash = diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 6c99d1fd..6ee26c49 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -111,6 +111,7 @@ struct SilcServerStruct { SilcIDList local_list; SilcIDList global_list; SilcHashTable watcher_list; + SilcHashTable watcher_list_pk; /* Table of connected sockets */ SilcSocketConnection *sockets; diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 8e545578..56791fab 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -1704,9 +1704,9 @@ silc_server_check_watcher_list_foreach(void *key, void *context, } } -/* This function checks whether the `client' nickname is being watched - by someone, and notifies the watcher of the notify change of notify - type indicated by `notify'. */ +/* This function checks whether the `client' nickname and/or 'client' + public key is being watched by someone, and notifies the watcher of the + notify change of notify type indicated by `notify'. */ bool silc_server_check_watcher_list(SilcServer server, SilcClientEntry client, @@ -1739,10 +1739,17 @@ bool silc_server_check_watcher_list(SilcServer server, n.new_nick = new_nick; n.notify = notify; - /* Send notify to all watchers */ + /* Send notify to all watchers watching this nickname */ silc_hash_table_find_foreach(server->watcher_list, hash, silc_server_check_watcher_list_foreach, &n); + /* Send notify to all watchers watching this public key */ + if (client->data.public_key) + silc_hash_table_find_foreach(server->watcher_list_pk, + client->data.public_key, + silc_server_check_watcher_list_foreach, + &n); + return TRUE; } -- 2.24.0