updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 21 Jun 2001 18:19:02 +0000 (18:19 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 21 Jun 2001 18:19:02 +0000 (18:19 +0000)
14 files changed:
CHANGES
TODO
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-channels.c
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/command.c
lib/silcclient/protocol.c
lib/silccore/silcpacket.h
lib/silcske/silcske.c
lib/silcske/silcske.h
lib/silcske/silcske_status.h

diff --git a/CHANGES b/CHANGES
index 2a159c486aac0ceb36e11616649fbde2f535d75f..022a733cb9d862df923593036671c23672a13175 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,31 @@ Thu Jun 21 17:10:08 CEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
          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 <priikone@poseidon.pspt.fi>
 
        * Fixed a possible crash in silc_packet_send_prepare.  It now
diff --git a/TODO b/TODO
index ad15d63429dcca71c1c09ca97793ac49063354f4..47181d968fc5dd52a898ae68db82b9109b33df3a 100644 (file)
--- 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
index f80deb805012c02bc71eb421056a174bcf7bb14a..bb95f116a7b3e7fb8860c5ac0b04865e71d31208 100644 (file)
@@ -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;
 
index 04d56233eba1917fe5c841b747ff08de26ba2552..71e597e2c1fc9fd049ef9884cd32e9a9685e89db 100644 (file)
@@ -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 : "");
   }
 }
 
index 2d0f493e7b928c462e1ffdcc69fd5ba3eccca9ea..48033266a4e0eb5f7ced7b97007340b52f18e0f3 100644 (file)
@@ -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)
index d4899345a514001b22b1d0e8a0d2ef5e5d741692..0c010bdfe97d377dd98ecf46207aaf7ac4143bfa 100644 (file)
@@ -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 */
index d20df0767481e7418b6f2ce4355f7e40f9451d74..cda5026b58dde21d9d39c46486fe3e32ec5e4223 100644 (file)
@@ -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);
 
index 0fbc909d2c6ee78558c89245e2beba485463f7cc..36c4c93d50613744a23bb06b9dcaa3b658ba2bf4 100644 (file)
@@ -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);
 }
 
index 6b90b3698c136d85fedc86de62a9e46cb767e921..ee12b1ea27fe48ede6136042b0603ae49cf9006e 100644 (file)
@@ -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;
 
index 9231f8cf5ac7e3f5f0e7b8f06d6d69f8ce15cdfa..bb9c651313c53e0b96d3983b30431bb6fba06b53 100644 (file)
@@ -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,
index 029c455debfcaee7e462fdc11c5a65c3e911bb71..2174b0fbdb8ed22c8e20fea16dadce8e65e54d38 100644 (file)
@@ -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
index 7d34d61aa2c426e706921c6064fdb51b3bb88bdf..6399b0f162158176bd2838b5032f90c1bf5265e5 100644 (file)
@@ -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);
index 14620c71a0635ddd4b9b8e5b6c60ef592b680405..63388dc2a1bd5c8da979cfedc458bb3c275222f9 100644 (file)
@@ -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 */
index c2f85c9c5b56b3f77f6a9bde73148589ce080f1d..7e03cecb6fb7fca9157e1f670526f512745bf5b7 100644 (file)
@@ -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