Do not clear inbuf for sockets that has QoS data in inbuf.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 30 Oct 2003 20:03:01 +0000 (20:03 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 30 Oct 2003 20:03:01 +0000 (20:03 +0000)
Check that outgoing purge is successful.
Use rekey period as rekey protocol timeout.

CHANGES
apps/silcd/packet_send.c
apps/silcd/protocol.c
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/protocol.c
lib/silccore/silcpacket.c

diff --git a/CHANGES b/CHANGES
index 7fc23a573334e46aa2101fa9461e4f1d75ef38ba..2b91d32d9173a3b92dfcc34515cd3b081db05b6f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,24 @@
+Thu Oct 30 20:23:40 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Check that packet queue purging was successful.  Affected
+         files lib/silcclient/client.c and silcd/packet_send.c.  Related
+         to MAC failed errors.
+
+       * Do not clear the inbuf even if it is empty if QoS was applied
+         to it.  Otherwise the QoS data is cleared and MAC failed error
+         will occur.  Affected file lib/silccore/silcpacket.c.
+
+       * Use the rekey period time as rekey protocol timeout value.
+         If the rekey does not succeed during the rekey period there's
+         something very wrong, and we most likely end up with wrong keys,
+         do graceful reconnect then.   Affected file silcd/server.c.
+
+       * Take reference of the socket in the parser context, as it's
+         possible to have the parsers in queue after the socket is
+         disconnected and this may cause crash.  Affected files are
+         lib/silccore/silcpacket.c, lib/silcclient/client.c and
+         silcd/server.c.
+
 Thu Oct 30 17:01:01 EET 2003 Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed KICK command reply sending, it sent to replies.
@@ -7,7 +28,7 @@ Wed Oct 30 14:06:52 CET 2003 Jochen Eisinger <jochen@penguin-breeder.org>
 
        * Finish the silc-mime.pl script. It now supports MIME type
          guessing using magic files, signing data messages, executing
-         MIME handlers in background. Affected files 
+         MIME handlers in background. Affected files
          irssi/scripts/silc-mime.pl and irssi/docs/help/in/mmsg.in
 
        * Changed MIME signal handler to make things easier for the perl
@@ -28,7 +49,7 @@ Sun Oct 26 21:19:02 EET 2003 Pekka Riikonen <priikone@silcnet.org>
 
 Fri Oct 24 21:24:12 CEST 2003  Jochen Eisinger <jochen@penguin-breeder.org>
 
-       * Fixed race condition between silc_client_init and 
+       * Fixed race condition between silc_client_init and
           my_silc_scheduler. Affected file irssi/src/silc/core/silc-core.c
 
 Fri Oct 24 16:43:40 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
@@ -46,20 +67,20 @@ Thu Oct 21 09:43:17 CEST 2003  Jochen Eisinger <jochen@penguin-breeder.org>
 
         * Modified the MIME parsing to allow \n and \r\n as delimiters.
          Affected files lib/silcutil/silcstrutil.c
-       
+
        * Cleaned up the escape/unescape functions for correctness and
          speed. Affected file irssi/src/silc/core/client_ops.c
 
        * Removed handling for data messages with Content-Type: text/*,
          moved parsing of MIME headers to the signal handler, added
-         support for signing and verifying data messages. Affected 
+         support for signing and verifying data messages. Affected
          files are irssi/docs/signals.txt, irssi/src/silc/core/client_ops.c,
          irssi/src/silc/core/silc-{servers,channels}.c
 
        * Added a perl script for handling data messages based on
-         information read from Mailcap files. New file 
+         information read from Mailcap files. New file
          irssi/scripts/silc-mime.pl
-       
+
 Mon Oct 20 16:08:22 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
 
        * Added new SILC_MESSAGE_FLAG_ACK that can  be used to
index b72ac0f3012379add36543e2f4e3b8ad19baafb8..3d2376aef46afae59fd968edc5676361ccdbc598 100644 (file)
@@ -35,7 +35,7 @@ int silc_server_packet_send_real(SilcServer server,
   int ret;
 
   /* If disconnecting, ignore the data */
-  if (SILC_IS_DISCONNECTING(sock))
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return -1;
 
   /* Send the packet */
@@ -98,7 +98,7 @@ void silc_server_packet_send(SilcServer server,
   idata = (SilcIDListData)sock->user_data;
 
   /* If disconnecting, ignore the data */
-  if (SILC_IS_DISCONNECTING(sock))
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return;
 
   /* If entry is disabled do not sent anything.  Allow hearbeat and
@@ -162,7 +162,7 @@ void silc_server_packet_send_dest(SilcServer server,
   int block_len = 0;
 
   /* If disconnecting, ignore the data */
-  if (!sock || SILC_IS_DISCONNECTING(sock))
+  if (!sock || SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return;
 
   idata = (SilcIDListData)sock->user_data;
@@ -2003,17 +2003,30 @@ void silc_server_send_connection_auth_request(SilcServer server,
 }
 
 /* Purge the outgoing packet queue to the network if there is data. This
-   function can be used to empty the packet queue. It is guaranteed that
-   after this function returns the outgoing data queue is empty. */
+   function can be used to empty the packet queue. */
 
 void silc_server_packet_queue_purge(SilcServer server,
                                    SilcSocketConnection sock)
 {
   if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
       !(SILC_IS_DISCONNECTING(sock)) && !(SILC_IS_DISCONNECTED(sock))) {
+    int ret;
+
     SILC_LOG_DEBUG(("Purging outgoing queue"));
+
     server->stat.packets_sent++;
-    silc_packet_send(sock, TRUE);
+    ret = silc_packet_send(sock, TRUE);
+    if (ret == -2) {
+      if (sock->outbuf && sock->outbuf->len > 0) {
+       /* Couldn't send all data, put the queue back up, we'll send
+          rest later. */
+       SILC_SET_CONNECTION_FOR_OUTPUT(server->schedule, sock->sock);
+       SILC_SET_OUTBUF_PENDING(sock);
+       return;
+      }
+    }
+
+    /* Purged all data */
     SILC_UNSET_OUTBUF_PENDING(sock);
     SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
     silc_buffer_clear(sock->outbuf);
index f232c3d84f94cb86384443fe1b7f766a502451d9..06e80fd4e696f2521c2d83ef100ecb8ed2f54f8e 100644 (file)
@@ -1400,6 +1400,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1456,6 +1457,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1524,6 +1526,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_server_packet_queue_purge(server, ctx->sock);
     silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                            0, NULL, 0, FALSE);
 
@@ -1531,6 +1534,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1558,6 +1562,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
       silc_server_protocol_rekey_generate_pfs(server, ctx, FALSE);
     else
       silc_server_protocol_rekey_generate(server, ctx, FALSE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* Assure that after calling final callback there cannot be pending
        executions for this protocol anymore. This just unregisters any
index 963746f9045acc439a214a8294b17724b529f0cd..8c635e2ed5813d613176d0fa4152c3f7cedd80ed 100644 (file)
@@ -2241,6 +2241,9 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     /* Do not send data to disconnected connection */
     if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
       SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
+      SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
+      SILC_UNSET_OUTBUF_PENDING(sock);
+      silc_buffer_clear(sock->outbuf);
       return;
     }
 
@@ -2397,6 +2400,11 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   int ret;
 
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+    SILC_LOG_DEBUG(("Connection is disconnected"));
+    goto out;
+  }
+
   server->stat.packets_received++;
 
   /* Parse the packet */
@@ -2473,6 +2481,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
 
  out:
   silc_packet_context_free(packet);
+  silc_socket_free(parse_ctx->sock);
   silc_free(parse_ctx);
 }
 
@@ -2487,6 +2496,13 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   bool ret;
 
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+    SILC_LOG_DEBUG(("Connection is disconnected"));
+    silc_socket_free(parser_context->sock);
+    silc_free(parser_context);
+    return FALSE;
+  }
+
   if (idata)
     idata->psn_receive = parser_context->packet->sequence + 1;
 
@@ -2497,9 +2513,17 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
   if (sock->protocol && sock->protocol->protocol &&
       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
+    silc_socket_dup(sock);
     silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
                                  parser_context);
 
+    if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+      SILC_LOG_DEBUG(("Connection is disconnected"));
+      silc_socket_free(sock);
+      return FALSE;
+    }
+    silc_socket_free(sock);
+
     /* Reprocess data since we'll return FALSE here.  This is because
        the idata->receive_key might have become valid in the last packet
        and we want to call this processor with valid cipher. */
@@ -2547,8 +2571,6 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
     silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
                                  parser_context);
     break;
-  default:
-    return TRUE;
   }
 
   return TRUE;
@@ -5356,6 +5378,14 @@ SILC_TASK_CALLBACK(silc_server_rekey_timeout)
     silc_ske_free(ctx->ske);
   silc_socket_free(sock);
   silc_free(ctx);
+
+  /* Disconnect since we failed to rekey, the keys are probably wrong. */
+  silc_server_disconnect_remote(server, sock,
+                               SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+
+  /* Reconnect */
+  if (sock->type != SILC_SOCKET_TYPE_CLIENT)
+    silc_server_create_connections(server);
 }
 
 /* A timeout callback for the re-key. We will be the initiator of the
@@ -5418,7 +5448,10 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback)
     silc_schedule_task_add(server->schedule, sock->sock,
                           silc_server_rekey_timeout,
                           proto_ctx,
-                          server->config->key_exchange_timeout, 0,
+                          (idata->rekey->timeout >
+                           server->config->key_exchange_timeout ?
+                           idata->rekey->timeout :
+                           server->config->key_exchange_timeout * 4), 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 
index 9fc554bf5568f91e2d7e4033da3446747e861a33..034b5cb05c6694d220c09a77471c0a286cbf6f20 100644 (file)
@@ -1042,6 +1042,7 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
 
   if (ret == SILC_PACKET_NONE) {
     silc_packet_context_free(packet);
+    silc_socket_free(parser_context->sock);
     silc_free(parser_context);
     return FALSE;
   }
@@ -1056,8 +1057,6 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
 
     /* Parse the incoming packet type */
     silc_client_packet_parse_type(client, sock, packet);
-    silc_packet_context_free(packet);
-    silc_free(parser_context);
 
     /* Reprocess the buffer since we'll return FALSE. This is because
        the `conn->internal->receive_key' might have become valid by processing
@@ -1071,12 +1070,17 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
                                  silc_client_packet_parse, client);
 
+    silc_packet_context_free(packet);
+    silc_socket_free(parser_context->sock);
+    silc_free(parser_context);
+
     return FALSE;
   }
 
   /* Parse the incoming packet type */
   silc_client_packet_parse_type(client, sock, packet);
   silc_packet_context_free(packet);
+  silc_socket_free(parser_context->sock);
   silc_free(parser_context);
   return TRUE;
 }
@@ -1495,8 +1499,21 @@ void silc_client_packet_queue_purge(SilcClient client,
                                    SilcSocketConnection sock)
 {
   if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
-      (SILC_IS_DISCONNECTED(sock) == FALSE)) {
-    silc_packet_send(sock, TRUE);
+      !(SILC_IS_DISCONNECTED(sock))) {
+    int ret;
+
+    ret = silc_packet_send(sock, TRUE);
+    if (ret == -2) {
+      if (sock->outbuf && sock->outbuf->len > 0) {
+       /* Couldn't send all data, put the queue back up, we'll send
+          rest later. */
+       SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
+       SILC_SET_OUTBUF_PENDING(sock);
+       return;
+      }
+    }
+
+    /* Purged all data */
     SILC_UNSET_OUTBUF_PENDING(sock);
     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
     silc_buffer_clear(sock->outbuf);
index bc229606f6b0f19b2baa618bcac556730b2a05fb..4ff4582147e8aa00e241bd2588345066681d456a 100644 (file)
@@ -938,6 +938,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -995,6 +996,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -1060,6 +1062,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_client_packet_queue_purge(client, ctx->sock);
     silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
                            NULL, 0, NULL, NULL, NULL, 0, FALSE);
 
@@ -1067,6 +1070,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1089,6 +1093,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
       silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
     else
       silc_client_protocol_rekey_generate(client, ctx, FALSE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* Protocol has ended, call the final callback */
     if (protocol->final_callback)
index 50f6369dfc2f2a89a33bf827734de1d1c61a05b2..f6e2ea15e155124ea6450127907c8734f16b59da 100644 (file)
@@ -387,7 +387,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     parse_ctx->packet->type = (SilcPacketType)header[3];
     parse_ctx->packet->padlen = (SilcUInt8)header[4];
     parse_ctx->packet->sequence = sequence++;
-    parse_ctx->sock = sock;
+    parse_ctx->sock = silc_socket_dup(sock);
     parse_ctx->context = parser_context;
 
     /* Check whether this is normal or special packet */
@@ -458,9 +458,14 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     memset(tmp, 0, sizeof(tmp));
   }
 
+  /* Don't clear buffer if pending data is in the buffer */
   if (cont == FALSE && sock->inbuf->len > 0)
     return TRUE;
 
+  /* Don't clear buffer if QoS data exists in the buffer */
+  if (sock->qos && sock->qos->data_len > 0)
+    return TRUE;
+
   SILC_LOG_DEBUG(("Clearing inbound buffer"));
   silc_buffer_clear(sock->inbuf);
   return TRUE;
@@ -491,6 +496,9 @@ static bool silc_packet_check_mac(SilcHmac hmac,
     /* Compare the MAC's */
     if (memcmp(packet_mac, mac, mac_len)) {
       SILC_LOG_ERROR(("MAC failed"));
+#if 1
+      abort();
+#endif
       return FALSE;
     }