X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_channel.c;h=68983d59c6f6692dc5adf3837deca7c95632cd1f;hp=6d38c42d02d96ed340279b952e0020af83c8a7be;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=5d90b0684f07a8a51d5dff5cd108a328ec82ffa9 diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index 6d38c42d..68983d59 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -1,16 +1,15 @@ /* - client_channel.c + client_channel.c - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 1997 - 2001 Pekka Riikonen + Copyright (C) 1997 - 2002 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - + the Free Software Foundation; version 2 of the License. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -40,20 +39,20 @@ void silc_client_send_channel_message(SilcClient client, SilcMessageFlags flags, unsigned char *data, SilcUInt32 data_len, - int force_send) + bool force_send) { - int i; - SilcSocketConnection sock = conn->sock; + SilcSocketConnection sock; SilcBuffer payload; SilcPacketContext packetdata; const SilcBufferStruct packet; SilcCipher cipher; SilcHmac hmac; unsigned char *id_string; - SilcUInt32 iv_len; int block_len; SilcChannelUser chu; + assert(client && conn && channel); + sock = conn->sock; SILC_LOG_DEBUG(("Sending packet to channel")); chu = silc_client_on_channel(channel, conn->local_entry); @@ -108,23 +107,14 @@ void silc_client_send_channel_message(SilcClient client, block_len = silc_cipher_get_block_len(cipher); - /* Generate IV */ - iv_len = silc_cipher_get_block_len(cipher); - if (channel->iv[0] == '\0') - for (i = 0; i < iv_len; i++) channel->iv[i] = - silc_rng_get_byte(client->rng); - else - silc_hash_make(client->internal->md5hash, channel->iv, iv_len, - channel->iv); - - /* Encode the channel payload. This also encrypts the message payload. */ - payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, - channel->iv, cipher, hmac, - client->rng); + /* Encode the message payload. This also encrypts the message payload. */ + payload = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE, + cipher, hmac, client->rng, NULL, + client->private_key, client->sha1hash); /* Get data used in packet header encryption, keys and stuff. */ - cipher = conn->send_key; - hmac = conn->hmac_send; + cipher = conn->internal->send_key; + hmac = conn->internal->hmac_send; id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL); /* Set the packet context pointers. The destination ID is always @@ -145,9 +135,9 @@ void silc_client_send_channel_message(SilcClient client, packetdata.dst_id_len); packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len; - packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len), block_len); + SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + + packetdata.src_id_len + + packetdata.dst_id_len), block_len, packetdata.padlen); /* Create the outgoing packet */ if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, @@ -158,7 +148,7 @@ void silc_client_send_channel_message(SilcClient client, /* Encrypt the header and padding of the packet. This is encrypted with normal session key shared with our server. */ - silc_packet_encrypt(cipher, hmac, conn->psn_send++, + silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++, (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len + packetdata.padlen); @@ -169,13 +159,19 @@ void silc_client_send_channel_message(SilcClient client, /* Now actually send the packet */ silc_client_packet_send_real(client, sock, force_send); + /* Check for mandatory rekey */ + if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD) + silc_schedule_task_add(client->schedule, sock->sock, + silc_client_rekey_callback, sock, 0, 1, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + out: silc_buffer_free(payload); silc_free(id_string); } typedef struct { - SilcChannelMessagePayload payload; + SilcMessagePayload payload; SilcChannelID *channel_id; } *SilcChannelClientResolve; @@ -206,24 +202,24 @@ static void silc_client_channel_message_cb(SilcClient client, silc_hash_table_add(clients[0]->channels, channel, chu); } - message = silc_channel_message_get_data(res->payload, &message_len); + message = silc_message_get_data(res->payload, &message_len); /* Pass the message to application */ client->internal->ops->channel_message( - client, conn, clients[0], channel, - silc_channel_message_get_flags(res->payload), - message, message_len); + client, conn, clients[0], channel, res->payload, + silc_message_get_flags(res->payload), + message, message_len); } out: - silc_channel_message_payload_free(res->payload); + silc_message_payload_free(res->payload); silc_free(res->channel_id); silc_free(res); } /* Process received message to a channel (or from a channel, really). This decrypts the channel message with channel specific key and parses the - channel payload. Finally it displays the message on the screen. */ + message payload. Finally it displays the message on the screen. */ void silc_client_channel_message(SilcClient client, SilcSocketConnection sock, @@ -231,7 +227,7 @@ void silc_client_channel_message(SilcClient client, { SilcClientConnection conn = (SilcClientConnection)sock->user_data; SilcBuffer buffer = packet->buffer; - SilcChannelMessagePayload payload = NULL; + SilcMessagePayload payload = NULL; SilcChannelID *id = NULL; SilcChannelEntry channel; SilcClientEntry client_entry; @@ -263,9 +259,9 @@ void silc_client_channel_message(SilcClient client, all private keys and check what decrypts correctly. */ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) { /* Parse the channel message payload. This also decrypts the payload */ - payload = silc_channel_message_payload_parse(buffer->data, buffer->len, - channel->channel_key, - channel->hmac); + payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE, + FALSE, channel->channel_key, + channel->hmac); /* If decryption failed and we have just performed channel key rekey we will use the old key in decryption. If that fails too then we @@ -275,9 +271,10 @@ void silc_client_channel_message(SilcClient client, goto out; } - payload = silc_channel_message_payload_parse(buffer->data, buffer->len, - channel->old_channel_key, - channel->old_hmac); + payload = silc_message_payload_parse(buffer->data, buffer->len, + FALSE, FALSE, + channel->old_channel_key, + channel->old_hmac); if (!payload) { goto out; } @@ -287,10 +284,10 @@ void silc_client_channel_message(SilcClient client, silc_dlist_start(channel->private_keys); while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) { - /* Parse the channel message payload. This also decrypts the payload */ - payload = silc_channel_message_payload_parse(buffer->data, buffer->len, - entry->cipher, - entry->hmac); + /* Parse the message payload. This also decrypts the payload */ + payload = silc_message_payload_parse(buffer->data, buffer->len, + FALSE, FALSE, + entry->cipher, entry->hmac); if (payload) break; } @@ -316,19 +313,19 @@ void silc_client_channel_message(SilcClient client, goto out; } - message = silc_channel_message_get_data(payload, &message_len); + message = silc_message_get_data(payload, &message_len); /* Pass the message to application */ client->internal->ops->channel_message( - client, conn, client_entry, channel, - silc_channel_message_get_flags(payload), - message, message_len); + client, conn, client_entry, channel, payload, + silc_message_get_flags(payload), + message, message_len); out: silc_free(id); silc_free(client_id); if (payload) - silc_channel_message_payload_free(payload); + silc_message_payload_free(payload); } /* Timeout callback that is called after a short period of time after the @@ -483,7 +480,7 @@ void silc_client_receive_channel_key(SilcClient client, currently it is not expected that the SKE key material would be used as channel private key. However, this API allows it. */ -int silc_client_add_channel_private_key(SilcClient client, +bool silc_client_add_channel_private_key(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel, const char *name, @@ -496,6 +493,8 @@ int silc_client_add_channel_private_key(SilcClient client, unsigned char hash[32]; SilcSKEKeyMaterial *keymat; + assert(client && channel); + if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) return FALSE; @@ -513,7 +512,7 @@ int silc_client_add_channel_private_key(SilcClient client, /* Produce the key material */ keymat = silc_calloc(1, sizeof(*keymat)); if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, - client->internal->md5hash, keymat) + client->sha1hash, keymat) != SILC_SKE_STATUS_OK) return FALSE; @@ -568,12 +567,14 @@ int silc_client_add_channel_private_key(SilcClient client, after calling this to protect the channel messages. Returns FALSE on on error, TRUE otherwise. */ -int silc_client_del_channel_private_keys(SilcClient client, +bool silc_client_del_channel_private_keys(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel) { SilcChannelPrivateKey entry; + assert(client && channel); + if (!channel->private_keys) return FALSE; @@ -602,13 +603,15 @@ int silc_client_del_channel_private_keys(SilcClient client, old channel key is used hereafter to protect the channel messages. This returns FALSE on error, TRUE otherwise. */ -int silc_client_del_channel_private_key(SilcClient client, +bool silc_client_del_channel_private_key(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel, SilcChannelPrivateKey key) { SilcChannelPrivateKey entry; + assert(client && channel); + if (!channel->private_keys) return FALSE; @@ -653,6 +656,8 @@ silc_client_list_channel_private_keys(SilcClient client, SilcChannelPrivateKey *keys = NULL, entry; SilcUInt32 count = 0; + assert(client && channel); + if (!channel->private_keys) return NULL; @@ -686,6 +691,7 @@ void silc_client_current_channel_private_key(SilcClient client, SilcChannelEntry channel, SilcChannelPrivateKey key) { + assert(client && channel); channel->curr_key = key; }