From: Pekka Riikonen Date: Thu, 30 Oct 2003 20:03:01 +0000 (+0000) Subject: Do not clear inbuf for sockets that has QoS data in inbuf. X-Git-Tag: silc.client.0.9.15~7 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=2519387056c5ed49da81513b2ae5b648e9cf9513;p=silc.git Do not clear inbuf for sockets that has QoS data in inbuf. Check that outgoing purge is successful. Use rekey period as rekey protocol timeout. --- diff --git a/CHANGES b/CHANGES index 7fc23a57..2b91d32d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,24 @@ +Thu Oct 30 20:23:40 EET 2003 Pekka Riikonen + + * 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 * Fixed KICK command reply sending, it sent to replies. @@ -7,7 +28,7 @@ Wed Oct 30 14:06:52 CET 2003 Jochen Eisinger * 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 Fri Oct 24 21:24:12 CEST 2003 Jochen Eisinger - * 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 @@ -46,20 +67,20 @@ Thu Oct 21 09:43:17 CEST 2003 Jochen Eisinger * 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 * Added new SILC_MESSAGE_FLAG_ACK that can be used to diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index b72ac0f3..3d2376ae 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -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); diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index f232c3d8..06e80fd4 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -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 diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 963746f9..8c635e2e 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -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); diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 9fc554bf..034b5cb0 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -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); diff --git a/lib/silcclient/protocol.c b/lib/silcclient/protocol.c index bc229606..4ff45821 100644 --- a/lib/silcclient/protocol.c +++ b/lib/silcclient/protocol.c @@ -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) diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index 50f6369d..f6e2ea15 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -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; }