+Thu Apr 12 14:42:51 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * If re-key protocol is active then process the incoming packets
+ synchronously since we must assure that icoming packets encrypted
+ with the old key is processed before the new keys is set to
+ use. This is true other packets than for REKEY packets.
+ Affected file silcd/server.c. The same was done to client library
+ as well, affected file lib/silcclient/client.c.
+
Thu Apr 12 12:01:52 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Fixed bug in client and server to accept the force send if
(*cmd->cb)(ctx);
} else {
+ if (app->conn->current_channel)
+ silc_client_send_channel_message(app->client,
+ app->conn,
+ app->conn->current_channel, NULL,
+ 0, "HALOO", 5, TRUE);
+
+#if 0
/* Normal message to a channel */
if (len && app->conn && app->conn->current_channel &&
app->conn->current_channel->on_channel == TRUE) {
app->conn->current_channel, NULL,
0, data, strlen(data), TRUE);
}
+#endif
}
out:
if (proto_ctx->pfs == FALSE)
/* Run the protocol */
- protocol->execute(server->timeout_queue, 0, protocol, sock->sock, 0, 0);
+ protocol->execute(server->timeout_queue, 0, protocol, sock->sock, 0, 1);
}
timeout!! */
hb_context = silc_calloc(1, sizeof(*hb_context));
hb_context->server = server;
- silc_socket_set_heartbeat(sock, 600, hb_context,
+ silc_socket_set_heartbeat(sock, 30, hb_context,
silc_server_perform_heartbeat,
server->timeout_queue);
/* Register re-key timeout */
- idata->rekey->timeout = 3600; /* XXX hardcoded */
+ idata->rekey->timeout = 60; /* XXX hardcoded */
idata->rekey->context = (void *)server;
silc_task_register(server->timeout_queue, sock->sock,
silc_server_rekey_callback,
timeout!! */
hb_context = silc_calloc(1, sizeof(*hb_context));
hb_context->server = server;
- silc_socket_set_heartbeat(sock, 600, hb_context,
+ silc_socket_set_heartbeat(sock, 30, hb_context,
silc_server_perform_heartbeat,
server->timeout_queue);
return FALSE;
}
-
+
/* Parses whole packet, received earlier. */
SILC_TASK_CALLBACK(silc_server_packet_parse_real)
break;
case SILC_SOCKET_TYPE_CLIENT:
/* Parse the packet with timeout (unless protocol is active) */
- silc_task_register(server->timeout_queue, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0,
- (sock->protocol ? 1 : 100000),
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+
+ /* If REKEY protocol is active we must proccess the packets synchronously
+ since we must assure that incoming packets that are encrypted with
+ the old key is processed before the new keys is set to use. */
+ if (SILC_SERVER_IS_REKEY(sock))
+ silc_server_packet_parse_real(server->timeout_queue, SILC_TASK_READ,
+ (void *)parser_context, sock->sock);
+ else
+ silc_task_register(server->timeout_queue, sock->sock,
+ silc_server_packet_parse_real,
+ (void *)parser_context, 0,
+ (sock->protocol ? 1 : 100000),
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
break;
case SILC_SOCKET_TYPE_SERVER:
case SILC_SOCKET_TYPE_ROUTER:
/* Packets from servers are parsed as soon as possible */
- silc_task_register(server->timeout_queue, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+
+ /* If REKEY protocol is active we must proccess the packets synchronously
+ since we must assure that incoming packets that are encrypted with
+ the old key is processed before the new keys is set to use. */
+ if (SILC_SERVER_IS_REKEY(sock))
+ silc_server_packet_parse_real(server->timeout_queue, SILC_TASK_READ,
+ (void *)parser_context, sock->sock);
+ else
+ silc_task_register(server->timeout_queue, sock->sock,
+ silc_server_packet_parse_real,
+ (void *)parser_context, 0, 1,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
break;
default:
return;
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock, 0, 0);
+ sock->protocol, sock->sock, 0, 1);
} else {
SilcServerKEInternalContext *proto_ctx =
(SilcServerKEInternalContext *)sock->protocol->context;
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock, 0, 0);
+ sock->protocol, sock->sock, 0, 1);
} else {
SilcServerKEInternalContext *proto_ctx =
(SilcServerKEInternalContext *)sock->protocol->context;
proto_ctx->packet = silc_packet_context_dup(packet);
/* Let the protocol handle the packet */
- sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock,
- 0, 100000);
+ if (proto_ctx->responder == FALSE)
+ sock->protocol->execute(server->timeout_queue, 0,
+ sock->protocol, sock->sock,
+ 0, 0);
+ else
+ sock->protocol->execute(server->timeout_queue, 0,
+ sock->protocol, sock->sock,
+ 0, 100000);
} else {
SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
"protocol active, packet dropped."));
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)rekey, 3600, 0,
+ (void *)rekey, 30, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
silc_server_channel_key_rekey);
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)channel->rekey, 3600, 0,
+ (void *)channel->rekey, 30, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
silc_server_channel_key_rekey);
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)channel->rekey, 3600, 0,
+ (void *)channel->rekey, 30, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
conn->remote_id_data_len = SILC_ID_SERVER_LEN;
/* Register re-key timeout */
- conn->rekey->timeout = 60; /* XXX hardcoded */
+ conn->rekey->timeout = 30; /* XXX hardcoded */
conn->rekey->context = (void *)client;
silc_task_register(client->timeout_queue, conn->sock->sock,
silc_client_rekey_callback,
silc_buffer_push(sock->outbuf,
sock->outbuf->data - sock->outbuf->head);
- ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
+ ret = silc_client_packet_send_real(client, sock, TRUE, FALSE);
/* If returned -2 could not write to connection now, will do
it later. */
SilcClient client = (SilcClient)parser_context->context;
/* Parse the packet */
- silc_task_register(client->timeout_queue, parser_context->sock->sock,
- silc_client_packet_parse_real,
- (void *)parser_context, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+
+ /* If REKEY protocol is active we must proccess the packets synchronously
+ since we must assure that incoming packets that are encrypted with
+ the old key is processed before the new keys is set to use. */
+ if (SILC_CLIENT_IS_REKEY(parser_context->sock))
+ silc_client_packet_parse_real(client->timeout_queue, SILC_TASK_READ,
+ (void *)parser_context,
+ parser_context->sock->sock);
+ else
+ silc_task_register(client->timeout_queue, parser_context->sock->sock,
+ silc_client_packet_parse_real,
+ (void *)parser_context, 0, 1,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
}
-
+
/* Parses the packet type and calls what ever routines the packet type
requires. This is done for all incoming packets. */
silc_packet_context_free(proto_ctx->packet);
proto_ctx->packet = silc_packet_context_dup(packet);
-
+
/* Let the protocol handle the packet */
- sock->protocol->execute(client->timeout_queue, 0,
- sock->protocol, sock->sock, 0, 100000);
+ if (proto_ctx->responder == FALSE)
+ sock->protocol->execute(client->timeout_queue, 0,
+ sock->protocol, sock->sock, 0, 0);
+ else
+ /* Let the protocol handle the packet */
+ sock->protocol->execute(client->timeout_queue, 0,
+ sock->protocol, sock->sock, 0, 100000);
} else {
SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
"protocol active, packet dropped."));
silc_client_packet_send_real(client, sock, force_send, FALSE);
}
+void silc_client_packet_send_flush(SilcClient client,
+ SilcSocketConnection sock,
+ SilcPacketType type,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ unsigned char *data,
+ uint32 data_len)
+{
+ SilcPacketContext packetdata;
+
+ /* First flush the packet queue. */
+
+ if (sock->outbuf->data - sock->outbuf->head)
+ silc_buffer_push(sock->outbuf,
+ sock->outbuf->data - sock->outbuf->head);
+
+ silc_client_packet_send_real(client, sock, TRUE, TRUE);
+
+ /* The packet has been sent and now it is time to set the connection
+ back to only for input. When there is again some outgoing data
+ available for this connection it will be set for output as well.
+ This call clears the output setting and sets it only for input. */
+ SILC_CLIENT_SET_CONNECTION_FOR_INPUT(sock->sock);
+ SILC_UNSET_OUTBUF_PENDING(sock);
+ silc_buffer_clear(sock->outbuf);
+
+ SILC_LOG_DEBUG(("Sending packet, type %d", type));
+
+ /* Get data used in the packet sending, keys and stuff */
+ if ((!cipher || !hmac || !dst_id) && sock->user_data) {
+ if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
+ cipher = ((SilcClientConnection)sock->user_data)->send_key;
+
+ if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
+ hmac = ((SilcClientConnection)sock->user_data)->hmac;
+
+ if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
+ dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
+ dst_id_type = SILC_ID_SERVER;
+ }
+ }
+
+ /* Set the packet context pointers */
+ packetdata.flags = 0;
+ packetdata.type = type;
+ if (sock->user_data &&
+ ((SilcClientConnection)sock->user_data)->local_id_data)
+ packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
+ else
+ packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
+ packetdata.src_id_len = SILC_ID_CLIENT_LEN;
+ packetdata.src_id_type = SILC_ID_CLIENT;
+ if (dst_id) {
+ packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
+ packetdata.dst_id_len = silc_id_get_len(dst_id_type);
+ packetdata.dst_id_type = dst_id_type;
+ } else {
+ packetdata.dst_id = NULL;
+ packetdata.dst_id_len = 0;
+ packetdata.dst_id_type = SILC_ID_NONE;
+ }
+ packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len + packetdata.dst_id_len;
+ packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
+
+ /* Prepare outgoing data buffer for packet sending */
+ silc_packet_send_prepare(sock,
+ SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len +
+ packetdata.dst_id_len,
+ packetdata.padlen,
+ data_len);
+
+ SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
+
+ packetdata.buffer = sock->outbuf;
+
+ /* Put the data to the buffer */
+ if (data && data_len)
+ silc_buffer_put(sock->outbuf, data, data_len);
+
+ /* Create the outgoing packet */
+ silc_packet_assemble(&packetdata);
+
+ /* Encrypt the packet */
+ if (cipher)
+ silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+
+ SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
+ sock->outbuf->data, sock->outbuf->len);
+
+ /* Now actually send the packet */
+ silc_client_packet_send_real(client, sock, TRUE, TRUE);
+}
+
/* Closes connection to remote end. Free's all allocated data except
for some information such as nickname etc. that are valid at all time.
If the `sock' is NULL then the conn->sock will be used. If `sock' is
void silc_client_private_message(SilcClient client,
SilcSocketConnection sock,
SilcPacketContext *packet);
+
+void silc_client_packet_send_flush(SilcClient client,
+ SilcSocketConnection sock,
+ SilcPacketType type,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ unsigned char *data,
+ uint32 data_len);
#endif
SilcClient client = (SilcClient)ctx->client;
/* Send the packet immediately */
- silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
- packet->data, packet->len, FALSE);
+ silc_client_packet_send_flush(client, ctx->sock, type, NULL, 0, NULL, NULL,
+ packet->data, packet->len);
}
/* Performs re-key as defined in the SILC protocol specification. */
*/
/* Send the REKEY_DONE to indicate we will take new keys into use */
- silc_client_packet_send(client, ctx->sock,
- SILC_PACKET_REKEY_DONE,
- NULL, 0, NULL, NULL, NULL, 0, FALSE);
+ silc_client_packet_send_flush(client, ctx->sock,
+ SILC_PACKET_REKEY_DONE,
+ NULL, 0, NULL, NULL, NULL, 0);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
*/
/* Start the re-key by sending the REKEY packet */
- silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
- NULL, 0, NULL, NULL, NULL, 0, FALSE);
+ silc_client_packet_send_flush(client, ctx->sock, SILC_PACKET_REKEY,
+ NULL, 0, NULL, NULL, NULL, 0);
if (ctx->pfs == TRUE) {
/*
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
- silc_client_packet_send(client, ctx->sock,
- SILC_PACKET_REKEY_DONE,
- NULL, 0, NULL, NULL, NULL, 0, FALSE);
+ silc_client_packet_send_flush(client, ctx->sock,
+ SILC_PACKET_REKEY_DONE,
+ NULL, 0, NULL, NULL, NULL, 0);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
- silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
- NULL, 0, NULL, NULL, NULL, 0, FALSE);
+ silc_client_packet_send_flush(client, ctx->sock, SILC_PACKET_REKEY_DONE,
+ NULL, 0, NULL, NULL, NULL, 0);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
/* Compare the HMAC's (buffer->tail has the packet's HMAC) */
if (memcmp(mac, buffer->tail, mac_len)) {
SILC_LOG_ERROR(("MAC failed"));
+ assert(FALSE);
return FALSE;
}