X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_channel.c;h=0f952373a55b747708aa10c6ea73b551526e5577;hb=6394d86063413bc1c473723f3ef971840195bcd3;hp=d08b3da00e8ed81986dd0003228302ca98ee66b7;hpb=9c4f7f18c31afa9dbaf4540c30cafd980b29c318;p=silc.git diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index d08b3da0..0f952373 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -49,6 +49,7 @@ void silc_client_send_channel_message(SilcClient client, SilcHmac hmac; unsigned char *id_string; uint32 iv_len; + int block_len; SILC_LOG_DEBUG(("Sending packet to channel")); @@ -86,13 +87,16 @@ void silc_client_send_channel_message(SilcClient client, if (!cipher || !hmac) return; + 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->md5hash, channel->iv, iv_len, channel->iv); + 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, @@ -118,7 +122,7 @@ void silc_client_send_channel_message(SilcClient client, 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)); + packetdata.dst_id_len), block_len); /* Prepare outgoing data buffer for packet sending */ silc_packet_send_prepare(sock, @@ -134,11 +138,12 @@ void silc_client_send_channel_message(SilcClient client, silc_buffer_put(sock->outbuf, payload->data, payload->len); /* Create the outgoing packet */ - silc_packet_assemble(&packetdata); + silc_packet_assemble(&packetdata, cipher); /* Encrypt the header and padding of the packet. This is encrypted with normal session key shared with our server. */ - silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + + silc_packet_encrypt(cipher, hmac, conn->psn_send++, + sock->outbuf, SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len + packetdata.padlen); @@ -151,17 +156,42 @@ void silc_client_send_channel_message(SilcClient client, silc_free(id_string); } +typedef struct { + SilcChannelMessagePayload payload; + SilcChannelID *channel_id; +} *SilcChannelClientResolve; + static void silc_client_channel_message_cb(SilcClient client, SilcClientConnection conn, SilcClientEntry *clients, uint32 clients_count, void *context) { - SilcPacketContext *packet = (SilcPacketContext *)context; + SilcChannelClientResolve res = (SilcChannelClientResolve)context; + + if (clients_count == 1) { + SilcIDCacheEntry id_cache = NULL; + SilcChannelEntry channel; + unsigned char *message; + + if (!silc_idcache_find_by_id_one(conn->channel_cache, res->channel_id, + &id_cache)) + goto out; + + channel = (SilcChannelEntry)id_cache->context; + message = silc_channel_message_get_data(res->payload, NULL); + + /* Pass the message to application */ + client->internal->ops->channel_message( + client, conn, clients[0], channel, + silc_channel_message_get_flags(res->payload), + message); + } - if (clients) - silc_client_channel_message(client, conn->sock, packet); - silc_packet_context_free(packet); + out: + silc_channel_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 @@ -208,7 +238,8 @@ 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, channel->channel_key, + payload = silc_channel_message_payload_parse(buffer->data, buffer->len, + channel->channel_key, channel->hmac); /* If decryption failed and we have just performed channel key rekey @@ -218,7 +249,7 @@ void silc_client_channel_message(SilcClient client, if (!channel->old_channel_key) goto out; - payload = silc_channel_message_payload_parse(buffer, + payload = silc_channel_message_payload_parse(buffer->data, buffer->len, channel->old_channel_key, channel->old_hmac); if (!payload) @@ -230,7 +261,8 @@ 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, entry->cipher, + payload = silc_channel_message_payload_parse(buffer->data, buffer->len, + entry->cipher, entry->hmac); if (payload) break; @@ -244,7 +276,8 @@ void silc_client_channel_message(SilcClient client, /* Find client entry */ silc_list_start(channel->clients); while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) { + if (SILC_ID_CLIENT_COMPARE(chu->client->id, client_id) && + chu->client->nickname) { found = TRUE; break; } @@ -252,18 +285,24 @@ void silc_client_channel_message(SilcClient client, if (!found) { /* Resolve the client info */ + SilcChannelClientResolve res = silc_calloc(1, sizeof(*res)); + res->payload = payload; + res->channel_id = id; silc_client_get_client_by_id_resolve(client, conn, client_id, silc_client_channel_message_cb, - silc_packet_context_dup(packet)); + res); + payload = NULL; + id = NULL; goto out; } message = silc_channel_message_get_data(payload, NULL); /* Pass the message to application */ - client->ops->channel_message(client, conn, chu->client, channel, - silc_channel_message_get_flags(payload), - message); + client->internal->ops->channel_message( + client, conn, chu->client, channel, + silc_channel_message_get_flags(payload), + message); out: if (id) @@ -305,7 +344,8 @@ void silc_client_save_channel_key(SilcClientConnection conn, SilcIDCacheEntry id_cache = NULL; SilcChannelKeyPayload payload; - payload = silc_channel_key_payload_parse(key_payload); + payload = silc_channel_key_payload_parse(key_payload->data, + key_payload->len); if (!payload) return; @@ -361,7 +401,9 @@ void silc_client_save_channel_key(SilcClientConnection conn, memcpy(channel->key, key, tmp_len); if (!silc_cipher_alloc(cipher, &channel->channel_key)) { - conn->client->ops->say(conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT, + conn->client->internal->ops->say( + conn->client, conn, + SILC_CLIENT_MESSAGE_AUDIT, "Cannot talk to channel: unsupported cipher %s", cipher); goto out; @@ -456,7 +498,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->md5hash, keymat) + client->internal->md5hash, keymat) != SILC_SKE_STATUS_OK) return FALSE;