/* This file includes the private message sending and receiving routines
and private message key handling routines. */
-#include "clientlibincludes.h"
+#include "silcincludes.h"
+#include "silcclient.h"
#include "client_internal.h"
/* Sends private message to remote client. If private message key has
SilcClientEntry client_entry,
SilcMessageFlags flags,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
int force_send)
{
SilcSocketConnection sock = conn->sock;
SilcBuffer buffer;
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcCipher cipher;
SilcHmac hmac;
+ int block_len;
SILC_LOG_DEBUG(("Sending private message"));
/* Encode private message payload */
buffer = silc_private_message_payload_encode(flags,
data_len, data,
- client_entry->send_key);
+ client_entry->send_key,
+ client->rng);
/* If we don't have private message specific key then private messages
are just as any normal packet thus call normal packet sending. If
/* We have private message specific key */
/* Get data used in the encryption */
- cipher = client_entry->send_key;
+ cipher = conn->send_key;
hmac = conn->hmac_send;
+ block_len = silc_cipher_get_block_len(cipher);
/* Set the packet context pointers. */
+ data = buffer->data;
+ data_len = buffer->len;
packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
packetdata.src_id = conn->local_id_data;
packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
packetdata.dst_id_len = silc_id_get_len(client_entry->id, SILC_ID_CLIENT);
packetdata.dst_id_type = SILC_ID_CLIENT;
- packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
+ data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len +
+ 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));
-
- /* 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,
- buffer->len);
-
- packetdata.buffer = sock->outbuf;
-
- /* Put the actual encrypted message payload data into the buffer. */
- silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
+ packetdata.dst_id_len), block_len);
/* Create the outgoing packet */
- silc_packet_assemble(&packetdata);
+ if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
+ data, data_len, (const SilcBuffer)&packet)) {
+ SILC_LOG_ERROR(("Error assembling packet"));
+ goto out;
+ }
/* Encrypt the header and padding of the packet. */
- cipher = conn->send_key;
- silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
+ silc_packet_encrypt(cipher, hmac, conn->psn_send++,
+ (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len +
packetdata.padlen);
- SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ SILC_LOG_HEXDUMP(("Private message packet, len %d", packet.len),
+ packet.data, packet.len);
/* Now actually send the packet */
- silc_client_packet_send_real(client, sock, force_send, FALSE);
+ silc_client_packet_send_real(client, sock, force_send);
silc_free(packetdata.dst_id);
out:
static void silc_client_private_message_cb(SilcClient client,
SilcClientConnection conn,
SilcClientEntry *clients,
- uint32 clients_count,
+ SilcUInt32 clients_count,
void *context)
{
SilcPacketContext *packet = (SilcPacketContext *)context;
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
SilcPrivateMessagePayload payload = NULL;
- SilcIDCacheEntry id_cache;
SilcClientID *remote_id = NULL;
SilcClientEntry remote_client;
SilcMessageFlags flags;
goto out;
/* Check whether we know this client already */
- if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)remote_id,
- NULL, NULL,
- silc_hash_client_id_compare, NULL,
- &id_cache)) {
+ remote_client = silc_client_get_client_by_id(client, conn, remote_id);
+ if (!remote_client || !remote_client->nickname) {
+ if (remote_client) {
+ if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
+ remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
+ goto out;
+ }
+ remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
+ }
+
/* Resolve the client info */
silc_client_get_client_by_id_resolve(client, conn, remote_id,
silc_client_private_message_cb,
return;
}
- remote_client = (SilcClientEntry)id_cache->context;
-
/* Parse the payload and decrypt it also if private message key is set */
- payload = silc_private_message_payload_parse(packet->buffer,
+ payload = silc_private_message_payload_parse(packet->buffer->data,
+ packet->buffer->len,
remote_client->receive_key);
if (!payload) {
silc_free(remote_id);
flags = silc_private_message_get_flags(payload);
/* Pass the private message to application */
- client->ops->private_message(client, conn, remote_client, flags,
- silc_private_message_get_message(payload,
- NULL));
+ client->internal->ops->private_message(
+ client, conn, remote_client, flags,
+ silc_private_message_get_message(payload,
+ NULL));
/* See if we are away (gone). If we are away we will reply to the
sender with the set away message. */
out:
if (payload)
silc_private_message_payload_free(payload);
- if (remote_id)
- silc_free(remote_id);
+ silc_free(remote_id);
}
/* Function that actually employes the received private message key */
static void silc_client_private_message_key_cb(SilcClient client,
SilcClientConnection conn,
SilcClientEntry *clients,
- uint32 clients_count,
+ SilcUInt32 clients_count,
void *context)
{
SilcPacketContext *packet = (SilcPacketContext *)context;
unsigned char *key;
- uint16 key_len;
+ SilcUInt16 key_len;
unsigned char *cipher;
int ret;
goto out;
/* Print some info for application */
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "Received private message key from %s%s%s %s%s%s",
- clients[0]->nickname,
- clients[0]->server ? "@" : "",
- clients[0]->server ? clients[0]->server : "",
- clients[0]->username ? "(" : "",
- clients[0]->username ? clients[0]->username : "",
- clients[0]->username ? ")" : "");
+ client->internal->ops->say(
+ client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+ "Received private message key from %s%s%s %s%s%s",
+ clients[0]->nickname,
+ clients[0]->server ? "@" : "",
+ clients[0]->server ? clients[0]->server : "",
+ clients[0]->username ? "(" : "",
+ clients[0]->username ? clients[0]->username : "",
+ clients[0]->username ? ")" : "");
out:
silc_packet_context_free(packet);
SilcClientEntry client_entry,
char *cipher,
unsigned char *key,
- uint32 key_len,
+ SilcUInt32 key_len,
bool generate_key,
bool responder)
{
unsigned char private_key[32];
- uint32 len;
+ SilcUInt32 len;
int i;
SilcSKEKeyMaterial *keymat;
}
/* Save the key */
- client_entry->key = silc_calloc(key_len, sizeof(*client_entry->key));
- memcpy(client_entry->key, key, key_len);
+ client_entry->key = silc_memdup(key, key_len);
client_entry->key_len = key_len;
/* Produce the key material as the protocol defines */
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;
SilcPrivateMessageKeys
silc_client_list_private_message_keys(SilcClient client,
SilcClientConnection conn,
- uint32 *key_count)
+ SilcUInt32 *key_count)
{
SilcPrivateMessageKeys keys;
- uint32 count = 0;
+ SilcUInt32 count = 0;
SilcIDCacheEntry id_cache;
SilcIDCacheList list;
SilcClientEntry entry;
silc_client_list_private_message_keys. */
void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
- uint32 key_count)
+ SilcUInt32 key_count)
{
silc_free(keys);
}