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
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
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
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;
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 : "");
}
{
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 : "");
}
}
}
}
+ 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)
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 */
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);
/* 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)
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);
}
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;
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,
/* 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
ske = silc_calloc(1, sizeof(*ske));
ske->status = SILC_SKE_STATUS_OK;
+ ske->users = 1;
return ske;
}
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) {
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. */
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) {
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);
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
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) {
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);
/* 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 */
SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH,
SILC_SKE_STATUS_INCORRECT_HASH,
SILC_SKE_STATUS_INCORRECT_PUBLIC_KEY,
+ SILC_SKE_STATUS_FREED,
} SilcSKEStatus;
#endif