From: Pekka Riikonen Date: Thu, 21 Jun 2001 18:19:02 +0000 (+0000) Subject: updates. X-Git-Tag: robodoc-323~163 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=3304e90317ca1ddc3c3301bdca6257f1f35da9e8 updates. --- diff --git a/CHANGES b/CHANGES index 2a159c48..022a733c 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,31 @@ Thu Jun 21 17:10:08 CEST 2001 Pekka Riikonen from the start and end of the arguments. Affected file is lib/silcutil/silcutil.c. + * Cancel and free any active protocol in the function + silc_server_close_connection. Affected file silcd/server.c. + + * Cancel and free any active protocol in the function + silc_client_close_connction. Affected file is + lib/silcclient/client.c. + + * Do not execute the KILL command for clients that are in + history (ie. they are not in the network). Affected file is + silcd/command.c. + + * Fixed KILL notify handling, client does not crash anymore. + Affected file irssi/src/silc/core/silc-channels.c. + + * Reduced the default packet buffer size from 2048 to 1024 in + lib/silccore/silcpacket.c. + + * Added SILC_SKE_STATUS_FREED SKE status type and a reference + counter to the SKE context that is incresed when the SKE library + performs async operation outside the library. If the outside + process frees the SKE context and FREED status will be set + and the library will detect after the sync operation that the + libary is freed. The affected files are + lib/silcske/silcske[_status].[ch]. + Tue Jun 19 22:10:36 EEST 2001 Pekka Riikonen * Fixed a possible crash in silc_packet_send_prepare. It now diff --git a/TODO b/TODO index ad15d634..47181d96 100644 --- a/TODO +++ b/TODO @@ -5,11 +5,6 @@ TODO/bugs in Irssi SILC client o /KICK does not remove the client from Irssi's NAMES list. - o Giving KILL command crashes the client. - - o Waiting the answer for accepting new key after the protocol has - timeout and then ansering Y will crash the client. - o Add PERL scripting support from Irssi CVS. o Add local commands to list the current server and client public keys @@ -43,6 +38,9 @@ TODO/bugs In SILC Client Library then it should attempt to resolve it at least once and no return NULL entry to the application. + o Add some silc_client_del_client and other deletion funtions for + application to delete client entrys from the cache. + o All protocol execution timeouts are hard coded. They should be configurable and the Irssi SILC client should be able to set them with for example /set key_exchange_timeout etc. The silc_client_alloc diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index f80deb80..bb95f116 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -184,7 +184,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn, or connecting failed. This is also the first time application receives the SilcClientConnection objecet which it should save somewhere. */ -void silc_connect(SilcClient client, SilcClientConnection conn, int success) +void silc_connect(SilcClient client, SilcClientConnection conn, int success) { SILC_SERVER_REC *server = conn->context; diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index 04d56233..71e597e2 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -426,11 +426,11 @@ static void event_kick(SILC_SERVER_REC *server, va_list va) if (client_entry == conn->local_entry) { printformat_module("fe-common/silc", server, channel_entry->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_KICKED_YOU, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU, channel_entry->channel_name, tmp ? tmp : ""); } else { printformat_module("fe-common/silc", server, channel_entry->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_KICKED, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED, client_entry->nickname, channel_entry->channel_name, tmp ? tmp : ""); } @@ -444,22 +444,20 @@ static void event_kill(SILC_SERVER_REC *server, va_list va) { SilcClientConnection conn = server->conn; SilcClientEntry client_entry; - SilcChannelEntry channel_entry; char *tmp; client_entry = va_arg(va, SilcClientEntry); tmp = va_arg(va, char *); - channel_entry = va_arg(va, SilcChannelEntry); if (client_entry == conn->local_entry) { - printformat_module("fe-common/silc", server, channel_entry->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_KILLED_YOU, - channel_entry->channel_name, tmp ? tmp : ""); + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, + tmp ? tmp : ""); } else { - printformat_module("fe-common/silc", server, channel_entry->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_KILLED, + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, client_entry->nickname, - channel_entry->channel_name, tmp ? tmp : ""); + tmp ? tmp : ""); } } diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 2d0f493e..48033266 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -2458,6 +2458,12 @@ SILC_SERVER_CMD_FUNC(kill) } } + if (remote_client->data.registered == FALSE) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID); + goto out; + } + /* Get comment */ comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2); if (tmp_len2 > 128) diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index d4899345..0c010bdf 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -316,7 +316,7 @@ void silc_server_notify(SilcServer server, if (channel->topic) silc_free(channel->topic); - channel->topic = silc_calloc(tmp_len, sizeof(*channel->topic)); + channel->topic = silc_calloc(tmp_len + 1, sizeof(*channel->topic)); memcpy(channel->topic, tmp, tmp_len); /* Send the same notify to the channel */ diff --git a/apps/silcd/server.c b/apps/silcd/server.c index d20df076..cda5026b 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -2080,6 +2080,14 @@ void silc_server_close_connection(SilcServer server, sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" : "Router"), sock->sock)); + /* If any protocol is active cancel its execution */ + if (sock->protocol) { + silc_protocol_cancel(sock->protocol, server->timeout_queue); + sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; + silc_protocol_execute_final(sock->protocol, server->timeout_queue); + sock->protocol = NULL; + } + /* We won't listen for this connection anymore */ silc_schedule_unset_listen_fd(sock->sock); diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 0fbc909d..36c4c93d 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -1156,16 +1156,34 @@ void silc_client_close_connection(SilcClient client, /* Close the actual connection */ silc_net_close_connection(sock->sock); + /* Cancel any active protocol */ + if (sock->protocol) { + if (sock->protocol->protocol->type == + SILC_PROTOCOL_CLIENT_KEY_EXCHANGE || + sock->protocol->protocol->type == + SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { + sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; + silc_protocol_execute_final(sock->protocol, client->timeout_queue); + sock->protocol = NULL; + /* The application will recall this function with these protocols + (the ops->connect client operation). */ + return; + } else { + sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; + silc_protocol_execute_final(sock->protocol, client->timeout_queue); + sock->protocol = NULL; + } + } + /* Free everything */ if (del && sock->user_data) { /* XXX Free all client entries and channel entries. */ - client->ops->say(client, sock->user_data, - "Closed connection to host %s", sock->hostname); - /* Clear ID caches */ - silc_idcache_del_all(conn->client_cache); - silc_idcache_del_all(conn->channel_cache); + if (conn->client_cache) + silc_idcache_del_all(conn->client_cache); + if (conn->channel_cache) + silc_idcache_del_all(conn->channel_cache); /* Free data */ if (conn->remote_host) @@ -1185,27 +1203,10 @@ void silc_client_close_connection(SilcClient client, if (conn->rekey) silc_free(conn->rekey); - conn->sock = NULL; - conn->remote_port = 0; - conn->remote_type = 0; - conn->send_key = NULL; - conn->receive_key = NULL; - conn->hmac_send = NULL; - conn->hmac_receive = NULL; - conn->local_id = NULL; - conn->local_id_data = NULL; - conn->remote_host = NULL; - conn->current_channel = NULL; - conn->pending_commands = NULL; - conn->rekey = NULL; - + memset(conn, 0, sizeof(*conn)); silc_client_del_connection(client, conn); } - if (sock->protocol) { - silc_protocol_free(sock->protocol); - sock->protocol = NULL; - } silc_socket_free(sock); } diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 6b90b369..ee12b1ea 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -793,6 +793,20 @@ SILC_CLIENT_CMD_FUNC(kill) silc_buffer_free(buffer); silc_buffer_free(idp); + /* Remove the client entry from the local cache. */ + silc_idcache_del_by_context(conn->client_cache, target); + if (target->nickname) + silc_free(target->nickname); + if (target->server) + silc_free(target->server); + if (target->id) + silc_free(target->id); + if (target->send_key) + silc_cipher_free(target->send_key); + if (target->receive_key) + silc_cipher_free(target->receive_key); + silc_free(target); + /* Notify application */ COMMAND; diff --git a/lib/silcclient/protocol.c b/lib/silcclient/protocol.c index 9231f8cf..bb9c6513 100644 --- a/lib/silcclient/protocol.c +++ b/lib/silcclient/protocol.c @@ -74,7 +74,7 @@ static void silc_client_verify_key_cb(bool success, void *context) silc_free(verify); } -/* Callback that is called when we have received KE2 payload from +/* Callback that is called when we have received KE payload from responder. We try to verify the public key now. */ void silc_client_protocol_ke_verify_key(SilcSKE ske, diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 029c455d..2174b0fb 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -35,9 +35,8 @@ /* Amount of bytes to be read from the socket connection at once. */ #define SILC_PACKET_READ_SIZE 16384 -/* Default byte size of the packet. This can be set larger if this - is not enough, we shall see. */ -#define SILC_PACKET_DEFAULT_SIZE 2048 +/* Default byte size of the packet. */ +#define SILC_PACKET_DEFAULT_SIZE 1024 /* Header length without source and destination ID's. */ #define SILC_PACKET_HEADER_LEN 8 + 2 diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 7d34d61a..6399b0f1 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -33,6 +33,7 @@ SilcSKE silc_ske_alloc() ske = silc_calloc(1, sizeof(*ske)); ske->status = SILC_SKE_STATUS_OK; + ske->users = 1; return ske; } @@ -41,6 +42,13 @@ SilcSKE silc_ske_alloc() void silc_ske_free(SilcSKE ske) { + ske->users--; + if (ske->users > 0) { + SILC_LOG_DEBUG(("Key Exchange set to FREED status")); + ske->status = SILC_SKE_STATUS_FREED; + return; + } + SILC_LOG_DEBUG(("Freeing Key Exchange object")); if (ske) { @@ -336,11 +344,22 @@ static void silc_ske_initiator_finish_final(SilcSKE ske, void *context) { SKEInitiatorFinish finish = (SKEInitiatorFinish)context; - SilcSKEKEPayload *payload = ske->ke2_payload; + SilcSKEKEPayload *payload; unsigned char hash[32]; uint32 hash_len; SilcPublicKey public_key = NULL; + /* If the SKE was freed during the async call then free it really now, + otherwise just decrement the reference counter. */ + if (ske->status == SILC_SKE_STATUS_FREED) { + silc_ske_free(ske); + return; + } else { + ske->users--; + } + + payload = ske->ke2_payload; + /* If the caller returns PENDING status SKE library will assume that the caller will re-call this callback when it is not anymore in PENDING status. */ @@ -382,8 +401,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske, SILC_LOG_DEBUG(("Verifying signature (HASH)")); /* Verify signature */ - silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk, - public_key->pk_len); + silc_pkcs_public_key_set(ske->prop->pkcs, public_key); if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data, payload->sign_len, hash, hash_len) == FALSE) { @@ -500,6 +518,7 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske, if (payload->pk_data && verify_key) { SILC_LOG_DEBUG(("Verifying public key")); + ske->users++; (*verify_key)(ske, payload->pk_data, payload->pk_len, payload->pk_type, verify_context, silc_ske_initiator_finish_final, finish); @@ -696,6 +715,15 @@ static void silc_ske_responder_phase2_final(SilcSKE ske, SilcSKEKEPayload *recv_payload, *send_payload; SilcMPInt *x, f; + /* If the SKE was freed during the async call then free it really now, + otherwise just decrement the reference counter. */ + if (ske->status == SILC_SKE_STATUS_FREED) { + silc_ske_free(ske); + return; + } else { + ske->users--; + } + recv_payload = ske->ke1_payload; /* If the caller returns PENDING status SKE library will assume that @@ -748,8 +776,7 @@ static void silc_ske_responder_phase2_final(SilcSKE ske, SILC_LOG_DEBUG(("Verifying signature (HASH_i)")); /* Verify signature */ - silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk, - public_key->pk_len); + silc_pkcs_public_key_set(ske->prop->pkcs, public_key); if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data, recv_payload->sign_len, hash, hash_len) == FALSE) { @@ -867,6 +894,7 @@ SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske, if (recv_payload->pk_data && verify_key) { SILC_LOG_DEBUG(("Verifying public key")); + ske->users++; (*verify_key)(ske, recv_payload->pk_data, recv_payload->pk_len, recv_payload->pk_type, verify_context, silc_ske_responder_phase2_final, finish); diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 14620c71..63388dc2 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -160,6 +160,10 @@ struct SilcSKEStruct { /* Current status of SKE */ SilcSKEStatus status; + + /* Reference counter. This is used when SKE library is performing async + operations, like public key verification. */ + int users; }; /* Prototypes */ diff --git a/lib/silcske/silcske_status.h b/lib/silcske/silcske_status.h index c2f85c9c..7e03cecb 100644 --- a/lib/silcske/silcske_status.h +++ b/lib/silcske/silcske_status.h @@ -43,6 +43,7 @@ typedef enum { SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH, SILC_SKE_STATUS_INCORRECT_HASH, SILC_SKE_STATUS_INCORRECT_PUBLIC_KEY, + SILC_SKE_STATUS_FREED, } SilcSKEStatus; #endif