{
int ret;
+ /* If rekey protocol is active we must assure that all packets are
+ sent through packet queue. */
+ if (SILC_SERVER_IS_REKEY(sock))
+ force_send = FALSE;
+
/* Send the packet */
ret = silc_packet_send(sock, force_send);
if (ret != -2)
if (dst_id) {
dst_id_data = silc_id_id2str(dst_id, dst_id_type);
- dst_id_len = silc_id_get_len(dst_id_type);
+ dst_id_len = silc_id_get_len(dst_id, dst_id_type);
}
/* Set the packet context pointers */
packetdata.type = type;
packetdata.flags = flags;
packetdata.src_id = silc_id_id2str(server->id, server->id_type);
- packetdata.src_id_len = SILC_ID_SERVER_LEN;
+ packetdata.src_id_len = silc_id_get_len(server->id, server->id_type);
packetdata.src_id_type = server->id_type;
packetdata.dst_id = dst_id_data;
packetdata.dst_id_len = dst_id_len;
if (idata) {
cipher = idata->send_key;
- hmac = idata->hmac;
+ hmac = idata->hmac_send;
}
/* Encrypt the packet */
if (dst_id) {
dst_id_data = silc_id_id2str(dst_id, dst_id_type);
- dst_id_len = silc_id_get_len(dst_id_type);
+ dst_id_len = silc_id_get_len(dst_id, dst_id_type);
}
if (src_id) {
src_id_data = silc_id_id2str(src_id, src_id_type);
- src_id_len = silc_id_get_len(src_id_type);
+ src_id_len = silc_id_get_len(src_id, src_id_type);
}
/* Set the packet context pointers */
if (idata) {
cipher = idata->send_key;
- hmac = idata->hmac;
+ hmac = idata->hmac_send;
}
/* Encrypt the packet */
/* If the packet is originated from our primary route we are
not allowed to send the packet. */
id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type);
- if (id && SILC_ID_SERVER_COMPARE(id, server->router->id)) {
+ if (id && !SILC_ID_SERVER_COMPARE(id, server->router->id)) {
idata = (SilcIDListData)sock->user_data;
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_packet_send_prepare(sock, 0, 0, buffer->len);
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac,
+ silc_packet_encrypt(idata->send_key, idata->hmac_send,
sock->outbuf, sock->outbuf->len);
SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_packet_send_prepare(sock, 0, 0, buffer->len);
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac,
+ silc_packet_encrypt(idata->send_key, idata->hmac_send,
sock->outbuf, sock->outbuf->len);
SILC_LOG_HEXDUMP(("Routed packet, len %d", sock->outbuf->len),
packetdata.flags = 0;
packetdata.type = type;
packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
- packetdata.src_id_len = SILC_ID_SERVER_LEN;
+ packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
packetdata.src_id_type = SILC_ID_SERVER;
packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
+ packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
packetdata.dst_id_type = SILC_ID_CHANNEL;
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
SILC_LOG_DEBUG(("Sending channel message to router for routing"));
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
}
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
}
silc_free(packetdata.dst_id);
}
+/* This checks whether the relayed packet came from router. If it did
+ then we'll need to encrypt it with the channel key. This is called
+ from the silc_server_packet_relay_to_channel. */
+
+static void
+silc_server_packet_relay_to_channel_encrypt(SilcServer server,
+ SilcSocketConnection sock,
+ SilcChannelEntry channel,
+ unsigned char *data,
+ unsigned int data_len)
+{
+ /* If we are router and the packet came from router and private key
+ has not been set for the channel then we must encrypt the packet
+ as it was decrypted with the session key shared between us and the
+ router which sent it. This is so, because cells does not share the
+ same channel key. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
+ channel->channel_key) {
+ SilcBuffer chp;
+ uint32 iv_len, i;
+ uint16 data_len, flags;
+
+ iv_len = silc_cipher_get_block_len(channel->channel_key);
+ if (channel->iv[0] == '\0')
+ for (i = 0; i < iv_len; i++) channel->iv[i] =
+ silc_rng_get_byte(server->rng);
+ else
+ silc_hash_make(server->md5hash, channel->iv, iv_len, channel->iv);
+
+ /* Encode new payload. This encrypts it also. */
+ SILC_GET16_MSB(flags, data);
+ SILC_GET16_MSB(data_len, data + 2);
+ chp = silc_channel_message_payload_encode(flags, data_len,
+ data + 4,
+ iv_len, channel->iv,
+ channel->channel_key,
+ channel->hmac);
+ memcpy(data, chp->data, chp->len);
+ silc_buffer_free(chp);
+ }
+}
+
/* This routine is explicitly used to relay messages to some channel.
Packets sent with this function we have received earlier and are
totally encrypted. This just sends the packet to all clients on
SilcChannelEntry channel,
void *sender,
SilcIdType sender_type,
+ void *sender_entry,
unsigned char *data,
uint32 data_len,
int force_send)
{
- int found = FALSE;
+ bool found = FALSE;
SilcSocketConnection sock = NULL;
SilcPacketContext packetdata;
SilcClientEntry client = NULL;
packetdata.flags = 0;
packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
packetdata.src_id = silc_id_id2str(sender, sender_type);
- packetdata.src_id_len = silc_id_get_len(sender_type);
+ packetdata.src_id_len = silc_id_get_len(sender, sender_type);
packetdata.src_id_type = sender_type;
packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
+ packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
packetdata.dst_id_type = SILC_ID_CHANNEL;
packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
packetdata.src_id_len +
packetdata.dst_id_len));
+ /* This encrypts the packet, if needed. It will be encrypted if
+ it came from the router thus it needs to be encrypted with the
+ channel key. If the channel key does not exist, then we know we
+ don't have a single local user on the channel. */
+ silc_server_packet_relay_to_channel_encrypt(server, sender_sock,
+ channel, data,
+ data_len);
+
/* If there are global users in the channel we will send the message
first to our router for further routing. */
if (server->server_type == SILC_SERVER && !server->standalone &&
SILC_LOG_DEBUG(("Sending channel message to router for routing"));
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
}
if (client) {
/* If sender is one on the channel do not send it the packet. */
- if (!found && !SILC_ID_CLIENT_COMPARE(client->id, sender)) {
+ if (!found && sender_type == SILC_ID_CLIENT &&
+ SILC_ID_CLIENT_COMPARE(client->id, sender)) {
found = TRUE;
continue;
}
/* Sender maybe server as well so we want to make sure that
we won't send the message to the server it came from. */
- if (!found && !SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
+ if (!found && SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
found = TRUE;
continue;
}
sock = (SilcSocketConnection)client->router->connection;
idata = (SilcIDListData)client->router;
+ /* Do not send to the sender. Check first whether the true
+ sender's router is same as this client's router. Also check
+ if the sender socket is the same as this client's router
+ socket. */
+ if (sender_entry &&
+ ((SilcClientEntry)sender_entry)->router == client->router)
+ continue;
if (sender_sock && sock == sender_sock)
continue;
memcpy(tmp, data, data_len);
/* Decrypt the channel message (we don't check the MAC) */
- if (!silc_channel_message_payload_decrypt(tmp, data_len,
+ /* XXX this could be optimized and removed all together by
+ taking a copy of the original data before encrypting it
+ and thus would not required decrypting. */
+ if (channel->channel_key &&
+ !silc_channel_message_payload_decrypt(tmp, data_len,
channel->channel_key,
NULL)) {
memset(tmp, 0, data_len);
}
continue;
}
-
+
/* Send the packet (to normal server) */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
}
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
- silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY, 0,
+ silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
}
SilcBuffer packet;
packet = silc_notify_payload_encode_args(type, argc, args);
- silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY, 0,
+ silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
}
SilcSocketConnection sock,
int broadcast,
SilcChannelID *old_id,
- SilcChannelID *new_id,
- uint32 id_len)
+ SilcChannelID *new_id)
{
SilcBuffer idp1, idp2;
SilcSocketConnection sock,
int broadcast,
SilcClientID *old_id,
- SilcClientID *new_id,
- uint32 id_len)
+ SilcClientID *new_id)
{
SilcBuffer idp1, idp2;
SilcSocketConnection sock,
int broadcast,
SilcChannelEntry channel,
- SilcClientID *client_id,
- uint32 client_id_len)
+ SilcClientID *client_id)
{
SilcBuffer idp1, idp2;
SilcSocketConnection sock,
int broadcast,
SilcChannelEntry channel,
- SilcClientID *client_id,
- uint32 client_id_len)
+ SilcClientID *client_id)
{
SilcBuffer idp;
SilcChannelEntry channel,
uint32 mode_mask,
void *id, SilcIdType id_type,
- uint32 id_len,
char *cipher, char *hmac)
{
SilcBuffer idp;
int broadcast,
SilcChannelEntry channel,
uint32 mode_mask,
- SilcClientID *client_id,
- uint32 client_id_len,
- SilcClientID *target,
- uint32 target_len)
+ void *id, SilcIdType id_type,
+ SilcClientID *target)
{
SilcBuffer idp1, idp2;
unsigned char mode[4];
- idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+ idp1 = silc_id_payload_encode((void *)id, id_type);
idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
SILC_PUT32_MSB(mode_mask, mode);
SilcSocketConnection sock,
int broadcast,
SilcClientID *client_id,
- uint32 client_id_len,
char *message)
{
SilcBuffer idp;
int broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
- uint32 client_id_len,
char *topic)
{
SilcBuffer idp;
int broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
- uint32 client_id_len,
char *comment)
{
SilcBuffer idp;
SilcSocketConnection sock,
int broadcast,
SilcClientID *client_id,
- uint32 client_id_len,
char *comment)
{
SilcBuffer idp;
SilcSocketConnection sock,
int broadcast,
SilcClientID *client_id,
- uint32 client_id_len,
uint32 mode_mask)
{
SilcBuffer idp;
int broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
- uint32 client_id_len,
char *add, char *del)
{
SilcBuffer idp, idp2;
packetdata.flags = 0;
packetdata.type = SILC_PACKET_NOTIFY;
packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
- packetdata.src_id_len = SILC_ID_SERVER_LEN;
+ packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
packetdata.src_id_type = SILC_ID_SERVER;
silc_list_start(client->channels);
idata = (SilcIDListData)c->router;
packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
- packetdata.dst_id_len = SILC_ID_SERVER_LEN;
+ packetdata.dst_id_len = silc_id_get_len(c->router->id, SILC_ID_SERVER);
packetdata.dst_id_type = SILC_ID_SERVER;
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
idata = (SilcIDListData)c;
packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
- packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
+ packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
packetdata.dst_id_type = SILC_ID_CLIENT;
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
/* Encode channel key packet */
tmp_len = strlen(channel->channel_key->cipher->name);
- packet = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, chid, tmp_len,
+ packet = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
+ SILC_ID_CHANNEL),
+ chid, tmp_len,
channel->channel_key->cipher->name,
channel->key_len / 8, channel->key);
SilcSocketConnection sock)
{
silc_server_packet_send(server, sock, SILC_PACKET_HEARTBEAT, 0,
- NULL, 0, TRUE);
+ NULL, 0, FALSE);
}
/* Generic function to relay packet we've received. This is used to relay