From: Pekka Riikonen Date: Sun, 22 Feb 2004 16:25:55 +0000 (+0000) Subject: Added SilcPublicKey to SilcClientEntry. X-Git-Tag: silc.server.0.9.17~9 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=faa295cdde7b356c833e527e2b6255e2f2e761f9 Added SilcPublicKey to SilcClientEntry. Fixed the get_clients_whois to work with attributes correctly. --- diff --git a/CHANGES b/CHANGES index e48d7389..61a90f08 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,18 @@ +Sun Feb 22 19:03:59 EET 2004 Pekka Riikonen + + * Added public key to the SIlcClientEntry. Affected files + are lib/silcclient/silcclient.h, command_reply.c, idlist.c + + * Fixed the get_clients_whois reply processing to return + exactly same entries server returned. Makes it possible + to search using attributes. Affected file is + lib/silcclient/idlist.c. + +Sat Feb 21 19:21:57 EET 2004 Pekka Riikonen + + * Save founder key to SilcChannelEntry. Affected files are + lib/silcclient/silcclient.h, command_reply.c, idlist.c. + Fri Feb 20 20:37:38 EET 2004 Pekka Riikonen * Call the monitor callback with _CLOSED status from the diff --git a/lib/silcclient/client_internal.h b/lib/silcclient/client_internal.h index 4155d61e..37558019 100644 --- a/lib/silcclient/client_internal.h +++ b/lib/silcclient/client_internal.h @@ -293,5 +293,9 @@ SilcBuffer silc_client_attributes_process(SilcClient client, void silc_client_packet_queue_purge(SilcClient client, SilcSocketConnection sock); SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback); +void +silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, + SilcStatus status, + bool notify); #endif diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index de06296d..c6c597de 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -1,6 +1,6 @@ /* - command.h + command.h Author: Pekka Riikonen @@ -122,7 +122,7 @@ void silc_client_command_pending_del(SilcClientConnection conn, SilcClientCommandPendingCallbacks silc_client_command_pending_check(SilcClientConnection conn, SilcClientCommandReplyContext ctx, - SilcCommand command, + SilcCommand command, SilcUInt16 ident, SilcUInt32 *callbacks_count); void silc_client_command_process(SilcClient client, diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 02e6c330..6cb2c1d7 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -160,7 +160,7 @@ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd) } } -static void +void silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, SilcStatus status, bool notify) @@ -968,7 +968,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) SilcUInt32 argc, mode = 0, len, list_count; char *topic, *tmp, *channel_name = NULL, *hmac; SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL; - SilcPublicKey founder_key = NULL; SilcBufferStruct chpklist; int i; @@ -1042,6 +1041,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) } conn->current_channel = channel; + channel->mode = mode; /* Get hmac */ hmac = silc_argument_get_arg_type(cmd->args, 11, NULL); @@ -1129,8 +1129,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) /* Get founder key */ tmp = silc_argument_get_arg_type(cmd->args, 15, &len); - if (tmp) - silc_pkcs_public_key_payload_decode(tmp, len, &founder_key); + if (tmp) { + if (channel->founder_key) + silc_pkcs_public_key_free(channel->founder_key); + channel->founder_key = NULL; + silc_pkcs_public_key_payload_decode(tmp, len, &channel->founder_key); + } /* Get channel public key list */ tmp = silc_argument_get_arg_type(cmd->args, 16, &len); @@ -1146,13 +1150,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) COMMAND_REPLY((SILC_ARGS, channel_name, channel, mode, 0, keyp ? keyp->head : NULL, NULL, NULL, topic, hmac, list_count, client_id_list, - client_mode_list, founder_key, tmp ? &chpklist : NULL)); + client_mode_list, channel->founder_key, + tmp ? &chpklist : NULL)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN); silc_client_command_reply_free(cmd); - if (founder_key) - silc_pkcs_public_key_free(founder_key); silc_buffer_free(keyp); silc_buffer_free(client_id_list); silc_buffer_free(client_mode_list); @@ -1960,9 +1963,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey) silc_hash_make(cmd->client->sha1hash, tmp + 4, len - 4, client_entry->fingerprint); } + if (!client_entry->public_key) { + client_entry->public_key = public_key; + public_key = NULL; + } /* Notify application */ - COMMAND_REPLY((SILC_ARGS, id_type, client_entry, public_key)); + COMMAND_REPLY((SILC_ARGS, id_type, client_entry, + client_entry->public_key)); } else if (id_type == SILC_ID_SERVER) { /* Received server's public key */ server_id = silc_id_payload_get_id(idp); diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 38864297..c6dbd425 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -121,9 +121,12 @@ typedef struct { SilcGetClientCallback completion; void *context; char *nickname; - char *server; + SilcClientEntry *clients; + SilcUInt32 clients_count; } *GetClientInternal; +/* Completion for IDENTIFY */ + SILC_CLIENT_CMD_FUNC(get_client_callback) { GetClientInternal i = (GetClientInternal)context; @@ -142,10 +145,126 @@ SILC_CLIENT_CMD_FUNC(get_client_callback) } silc_free(i->nickname); - silc_free(i->server); silc_free(i); } +/* Completion for WHOIS */ + +SILC_CLIENT_CMD_FUNC(get_client_callback_wc) +{ + GetClientInternal i = (GetClientInternal)context; + SilcClientCommandReplyContext cmd = context2; + SilcClientID *client_id = NULL; + SilcClientEntry client_entry = NULL; + unsigned char *id_data; + SilcUInt32 len; + + /* Get the client entry just returned from server */ + id_data = silc_argument_get_arg_type(cmd->args, 2, &len); + if (id_data) + client_id = silc_id_payload_parse_id(id_data, len, NULL); + if (client_id) + client_entry = silc_client_get_client_by_id(i->client, + i->conn, client_id); + if (!client_entry) { + if (!SILC_STATUS_IS_ERROR(cmd->status) && + cmd->status != SILC_STATUS_OK && + cmd->status != SILC_STATUS_LIST_END) { + silc_free(client_id); + return; + } + + i->completion(i->client, i->conn, i->clients, i->clients_count, + i->context); + silc_free(client_id); + silc_free(i->clients); + silc_free(i->nickname); + silc_free(i); + return; + } + + /* Save the client */ + i->clients = silc_realloc(i->clients, + (sizeof(*i->clients) * (i->clients_count + 1))); + i->clients[i->clients_count] = client_entry; + i->clients_count++; + + /* Return if more data is expected */ + if (cmd->status != SILC_STATUS_OK && + cmd->status != SILC_STATUS_LIST_END) { + silc_free(client_id); + return; + } + + i->completion(i->client, i->conn, i->clients, i->clients_count, + i->context); + + silc_free(client_id); + silc_free(i->clients); + silc_free(i->nickname); + silc_free(i); +} + +/* Our own WHOIS reply processor. */ + +SILC_CLIENT_CMD_FUNC(get_client_callback_w) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + + SILC_LOG_DEBUG(("Start")); + + if (!silc_command_get_status(cmd->payload, NULL, NULL)) { + if (SILC_STATUS_IS_ERROR(cmd->status)) + goto out; + if (cmd->status == SILC_STATUS_LIST_END) + goto out; + goto err; + } + + /* Save WHOIS info */ + silc_client_command_reply_whois_save(cmd, cmd->status, FALSE); + + /* Call pending completion for each reply */ + if (cmd->status != SILC_STATUS_OK && + cmd->status != SILC_STATUS_LIST_END) { + if (cmd->callbacks[0].callback) + (*cmd->callbacks[0].callback)(cmd->callbacks[0].context, cmd); + silc_client_command_reply_free(cmd); + return; + } + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS); + + err: + /* If we received notify for invalid ID we'll remove the ID if we + have it cached. */ + if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { + SilcClientEntry client_entry; + SilcUInt32 tmp_len; + unsigned char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd->payload), + 2, &tmp_len); + if (tmp) { + SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (client_id) { + client_entry = silc_client_get_client_by_id(cmd->client, conn, + client_id); + if (client_entry) + silc_client_del_client(cmd->client, conn, client_entry); + silc_free(client_id); + } + } + } + + /* Unregister this command reply */ + silc_client_command_unregister(cmd->client, SILC_COMMAND_WHOIS, + NULL, silc_client_command_reply_whois_i, + cmd->ident); + silc_client_command_reply_free(cmd); +} + /* Finds client entry or entries by the `nickname' and `server'. The completion callback will be called when the client entries has been found. @@ -166,18 +285,17 @@ void silc_client_get_clients_i(SilcClient client, { GetClientInternal i; int len; - char *userhost; + char *userhost = NULL; assert(client && conn); - if (!nickname) + if (!nickname && !attributes) return; i = silc_calloc(1, sizeof(*i)); i->client = client; i->conn = conn; - i->nickname = strdup(nickname); - i->server = server ? strdup(server) : NULL; + i->nickname = nickname ? strdup(nickname) : NULL; i->completion = completion; i->context = context; @@ -187,7 +305,7 @@ void silc_client_get_clients_i(SilcClient client, silc_strncat(userhost, len, nickname, strlen(nickname)); silc_strncat(userhost, len, "@", 1); silc_strncat(userhost, len, server, strlen(server)); - } else { + } else if (nickname) { userhost = silc_memdup(nickname, strlen(nickname)); } @@ -200,21 +318,26 @@ void silc_client_get_clients_i(SilcClient client, silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, 1, 1, userhost, strlen(userhost)); + + /* Add pending callback */ + silc_client_command_pending(conn, command, conn->cmd_ident, + silc_client_command_get_client_callback, + (void *)i); } else { silc_client_command_register(client, command, NULL, NULL, - silc_client_command_reply_whois_i, 0, + silc_client_command_get_client_callback_w, 0, ++conn->cmd_ident); /* Send the command */ silc_client_command_send(client, conn, command, conn->cmd_ident, 2, - 1, userhost, strlen(userhost), + 1, userhost, userhost ? strlen(userhost) : 0, 3, attributes ? attributes->data : NULL, attributes ? attributes->len : 0); - } - /* Add pending callback */ - silc_client_command_pending(conn, command, conn->cmd_ident, - silc_client_command_get_client_callback, - (void *)i); + /* Add pending callback */ + silc_client_command_pending(conn, command, conn->cmd_ident, + silc_client_command_get_client_callback_wc, + (void *)i); + } silc_free(userhost); } @@ -903,6 +1026,8 @@ void silc_client_del_client_entry(SilcClient client, silc_free(client_entry->server); silc_free(client_entry->id); silc_free(client_entry->fingerprint); + if (client_entry->public_key) + silc_pkcs_public_key_free(client_entry->public_key); silc_hash_table_free(client_entry->channels); if (client_entry->send_key) silc_cipher_free(client_entry->send_key); @@ -1001,6 +1126,8 @@ bool silc_client_del_channel(SilcClient client, SilcClientConnection conn, silc_free(channel->channel_name); silc_free(channel->topic); silc_free(channel->id); + if (channel->founder_key) + silc_pkcs_public_key_free(channel->founder_key); silc_free(channel->key); if (channel->channel_key) silc_cipher_free(channel->channel_key); diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index 3f337ec9..21674db8 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -211,6 +211,7 @@ struct SilcClientEntryStruct { SilcDList attrs; /* Requested Attributes (maybe NULL) */ unsigned char *fingerprint; /* Fingerprint of client's public key */ SilcUInt32 fingerprint_len; /* Length of the fingerprint */ + SilcPublicKey public_key; /* User's public key, may be NULL */ /* Private message keys */ SilcCipher send_key; /* Private message key for sending */ @@ -256,6 +257,7 @@ struct SilcChannelEntryStruct { SilcChannelID *id; /* Channel ID */ SilcUInt32 mode; /* Channel mode, ChannelModes. */ char *topic; /* Current topic, may be NULL */ + SilcPublicKey founder_key; /* Founder key, may be NULL */ /* All clients that has joined this channel. The key to the table is the SilcClientEntry and the context is SilcChannelUser context. */