other cells as well. Added this support for the router in the
silcd/packet_receive.c.
+ * Added new local command NOTICE to send notice message on
+ channel. Affected file silc/local_command.[ch].
+
Wed Mar 28 23:55:54 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Added new local command ME to the client. It is used to send
TODO In SILC Client Library
===========================
- o TODO in commands (lib/silcclient/command.c and
- silc/silclient/command_reply.c):
-
- o RESTART command is not implemented
-
o Client library crashes if for example server timeouts protocol
execution and disconnects the client. The client, on the other hand
may still assume that the connection is active, even after receiving
clients before setting the status. Good fix for this would be
to make sure that the clients table does not include any
unregistered clients in the first place.
+ o Cleanup LEAVE command's channel key sending, it can be done
+ simpler by one function: silc_server_send_channel_key.
o TODO in notify types (packet_receive.c):
silc_print(client, "* %s %s", sender ? sender->nickname : "[<unknown>]",
msg);
else if (flags & SILC_MESSAGE_FLAG_NOTICE)
- silc_print(client, "-%s- %s", sender ? sender->nickname : "[<unknown>]",
+ silc_print(client, "- %s %s", sender ? sender->nickname : "[<unknown>]",
msg);
else
silc_print(client, "<%s> %s", sender ? sender->nickname : "[<unknown>]",
"[<unknown>]",
channel->channel_name, msg);
else if (flags & SILC_MESSAGE_FLAG_NOTICE)
- silc_print(client, "-%s:%s- %s", sender ? sender->nickname :
+ silc_print(client, "- %s:%s %s", sender ? sender->nickname :
"[<unknown>]",
channel->channel_name, msg);
else
SILC_CLIENT_LCMD(away, AWAY, "AWAY", 0, 2),
SILC_CLIENT_LCMD(key, KEY, "KEY", 0, 7),
SILC_CLIENT_LCMD(me, ME, "ME", 0, 3),
+ SILC_CLIENT_LCMD(notice, NOTICE, "NOTICE", 0, 3),
{ NULL, 0, NULL, 0, 0 },
};
out:
silc_client_command_free(cmd);
}
+
+/* Sends an notice to the channel. */
+
+SILC_CLIENT_LCMD_FUNC(notice)
+{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClientConnection conn = cmd->conn;
+ SilcClient client = cmd->client;
+ SilcChannelEntry channel_entry;
+ char *name;
+
+ if (!cmd->conn) {
+ silc_say(client, conn,
+ "You are not connected to a server, use /SERVER to connect");
+ goto out;
+ }
+
+ if (cmd->argc < 3) {
+ silc_say(client, conn, "Usage: /ME <channel> <action message>");
+ goto out;
+ }
+
+ if (cmd->argv[1][0] == '*') {
+ if (!conn->current_channel) {
+ cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
+ goto out;
+ }
+ name = conn->current_channel->channel_name;
+ } else {
+ name = cmd->argv[1];
+ }
+
+ channel_entry = silc_client_get_channel(client, conn, name);
+ if (!channel_entry) {
+ silc_say(client, conn, "You are not on that channel");
+ goto out;
+ }
+
+ /* Send the action message */
+ silc_client_send_channel_message(client, conn, channel_entry, NULL,
+ SILC_MESSAGE_FLAG_NOTICE,
+ cmd->argv[2], cmd->argv_lens[2], TRUE);
+
+ silc_print(client, "- %s %s", conn->nickname, cmd->argv[2]);
+
+ out:
+ silc_client_command_free(cmd);
+}
#define SILC_LOCAL_COMMAND_AWAY 6
#define SILC_LOCAL_COMMAND_KEY 7
#define SILC_LOCAL_COMMAND_ME 8
+#define SILC_LOCAL_COMMAND_NOTICE 9
/* Macros */
SILC_CLIENT_LCMD_FUNC(away);
SILC_CLIENT_LCMD_FUNC(key);
SILC_CLIENT_LCMD_FUNC(me);
+SILC_CLIENT_LCMD_FUNC(notice);
#endif
unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
SilcClientEntry client;
SilcChannelClientEntry chl;
- SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
+ SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
unsigned short ident = silc_command_get_ident(cmd->payload);
char check[512];
/* Send the channel key. This is broadcasted to the channel but is not
sent to the client who is joining to the channel. */
- silc_server_send_channel_key(server, NULL, channel,
- server->server_type == SILC_ROUTER ?
- FALSE : !server->standalone);
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+ silc_server_send_channel_key(server, NULL, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
/* Join the client to the channel by adding it to channel's user list.
Add also the channel to client entry's channels list for fast cross-
SILC_PUT32_MSB(channel->mode, mode);
SILC_PUT32_MSB(created, tmp2);
SILC_PUT32_MSB(user_count, tmp3);
- tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->cipher->name,
- channel->key_len / 8, channel->key);
- silc_free(tmp);
+
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
+ strlen(channel->channel_key->
+ cipher->name),
+ channel->channel_key->cipher->name,
+ channel->key_len / 8, channel->key);
+ silc_free(tmp);
+ }
+
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
SILC_STATUS_OK, ident, 13,
4, clidp->data, clidp->len,
5, mode, 4,
6, tmp2, 4,
- 7, keyp->data, keyp->len,
+ 7, keyp ? keyp->data : NULL,
+ keyp ? keyp->len : 0,
8, channel->ban_list,
channel->ban_list ?
strlen(channel->ban_list) : 0,
target_client->id, SILC_ID_CLIENT_LEN,
comment);
- /* Re-generate channel key */
- silc_server_create_channel_key(server, channel, 0);
-
- /* Send the channel key to the channel. The key of course is not sent
- to the client who was kicked off the channel. */
- silc_server_send_channel_key(server, target_client->connection, channel,
- server->server_type == SILC_ROUTER ?
- FALSE : !server->standalone);
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ /* Re-generate channel key */
+ silc_server_create_channel_key(server, channel, 0);
+
+ /* Send the channel key to the channel. The key of course is not sent
+ to the client who was kicked off the channel. */
+ silc_server_send_channel_key(server, target_client->connection, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ }
out:
silc_server_command_free(cmd);
if (!i)
goto out;
- /* Re-generate channel key */
- silc_server_create_channel_key(server, channel, 0);
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ /* Re-generate channel key */
+ silc_server_create_channel_key(server, channel, 0);
- /* Encode channel key payload to be distributed on the channel */
- packet =
- silc_channel_key_payload_encode(len, tmp,
- strlen(channel->channel_key->cipher->name),
- channel->channel_key->cipher->name,
- channel->key_len / 8, channel->key);
+ /* Encode channel key payload to be distributed on the channel */
+ packet =
+ silc_channel_key_payload_encode(len, tmp,
+ strlen(channel->channel_key->
+ cipher->name),
+ channel->channel_key->cipher->name,
+ channel->key_len / 8, channel->key);
+
+ /* If we are normal server then we will send it to our router. If we
+ are router we will send it to all local servers that has clients on
+ the channel */
+ if (server->server_type == SILC_SERVER) {
+ if (!server->standalone)
+ silc_server_packet_send(server,
+ cmd->server->router->connection,
+ SILC_PACKET_CHANNEL_KEY, 0, packet->data,
+ packet->len, FALSE);
+ } else {
+
+ }
- /* If we are normal server then we will send it to our router. If we
- are router we will send it to all local servers that has clients on
- the channel */
- if (server->server_type == SILC_SERVER) {
- if (!server->standalone)
- silc_server_packet_send(server,
- cmd->server->router->connection,
- SILC_PACKET_CHANNEL_KEY, 0, packet->data,
- packet->len, FALSE);
- } else {
+ /* Send to locally connected clients on the channel */
+ silc_server_packet_send_local_channel(server, channel,
+ SILC_PACKET_CHANNEL_KEY, 0,
+ packet->data, packet->len, FALSE);
+ silc_buffer_free(packet);
}
- /* Send to locally connected clients on the channel */
- silc_server_packet_send_local_channel(server, channel,
- SILC_PACKET_CHANNEL_KEY, 0,
- packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
silc_free(id);
out:
unsigned char *id_string;
char *channel_name, *tmp;
unsigned int mode, created;
- SilcBuffer keyp, client_id_list, client_mode_list;
+ SilcBuffer keyp = NULL, client_id_list, client_mode_list;
COMMAND_CHECK_STATUS;
/* Get channel key */
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
- if (!tmp)
- goto out;
- keyp = silc_buffer_alloc(len);
- silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
- silc_buffer_put(keyp, tmp, len);
+ if (tmp) {
+ keyp = silc_buffer_alloc(len);
+ silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
+ silc_buffer_put(keyp, tmp, len);
+ }
id = silc_id_payload_parse_id(id_string, id_len);
if (!id)
entry->mode = mode;
/* Save channel key */
- silc_server_save_channel_key(server, keyp, entry);
- silc_buffer_free(keyp);
+ if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ silc_server_save_channel_key(server, keyp, entry);
+ }
+ if (keyp)
+ silc_buffer_free(keyp);
/* Save the users to the channel */
silc_server_save_users_on_channel(server, cmd->sock, entry,
SILC_GET32_MSB(mode, tmp);
+ /* If the channel had private keys set and the mode was removed then
+ we must re-generate and re-distribute a new channel key */
+ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
+ !(mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ /* Re-generate channel key */
+ silc_server_create_channel_key(server, channel, 0);
+
+ /* Send the channel key. This sends it to our local clients and if
+ we are normal server to our router as well. */
+ silc_server_send_channel_key(server, NULL, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ }
+
/* Change mode */
channel->mode = mode;
silc_free(channel_id);
SilcBuffer buffer = packet->buffer;
SilcChannelEntry channel;
- if (packet->src_id_type != SILC_ID_SERVER)
+ if (packet->src_id_type != SILC_ID_SERVER ||
+ (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER))
return;
/* Save the channel key */
/* Create new key for the channel and send it to the server and
everybody else possibly on the channel. */
- silc_server_create_channel_key(server, channel, 0);
-
- /* Send to the channel */
- silc_server_send_channel_key(server, sock, channel, FALSE);
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+ silc_server_create_channel_key(server, channel, 0);
+
+ /* Send to the channel */
+ silc_server_send_channel_key(server, sock, channel, FALSE);
+
+ /* Send to the server */
+ chk = silc_channel_key_payload_encode(id_len, id,
+ strlen(channel->channel_key->
+ cipher->name),
+ channel->channel_key->
+ cipher->name,
+ channel->key_len / 8,
+ channel->key);
+ silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
+ chk->data, chk->len, FALSE);
+ silc_buffer_free(chk);
+ }
- /* Send to the server */
- chk = silc_channel_key_payload_encode(id_len, id,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->cipher->name,
- channel->key_len / 8,
- channel->key);
- silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
- chk->data, chk->len, FALSE);
- silc_buffer_free(chk);
silc_free(channel_id);
/* Since the channel is coming from server and we also know about it
} else {
/* Private key mode is set, we don't have the channel key, so
just re-encrypt the entire packet and send it to the router. */
- silc_server_packet_send_dest(server, sock,
- SILC_PACKET_CHANNEL_MESSAGE, 0,
- channel->id, SILC_ID_CHANNEL,
- data, data_len, force_send);
+ silc_server_packet_send_srcdest(server, sock,
+ SILC_PACKET_CHANNEL_MESSAGE, 0,
+ sender, sender_type,
+ channel->id, SILC_ID_CHANNEL,
+ data, data_len, force_send);
}
continue;
}
signoff_message, signoff_message ?
strlen(signoff_message) : 0);
- if (keygen) {
+ if (keygen && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
/* Re-generate channel key */
silc_server_create_channel_key(server, channel, 0);
SILC_LOG_DEBUG(("Generating channel key"));
+ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
+ SILC_LOG_DEBUG(("Channel has private keys, will not generate new key"));
+ return;
+ }
+
if (!channel->channel_key)
if (!silc_cipher_alloc("aes-256-cbc", &channel->channel_key))
return;
[Cipher]
-aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
-aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
-aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
-twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
-twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
-twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
-mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
-mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
-mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
+rc6:../lib/silcsim/modules/rc6.sim.so:16:16
+twofish:../lib/silcsim/modules/twofish.sim.so:16:16
+mars:../lib/silcsim/modules/mars.sim.so:16:16
none:../lib/silcsim/modules/none.sim.so:0:0
-[Hash]
+[Hash]
md5::64:16
sha1::64:20
[hmac]
hmac-sha1-96:sha1:12
hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20
hmac-md5:md5:16
#[PKCS]
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
[ListenPort]
-212.146.42.253:212.146.42.253:1334
+10.2.1.7:10.2.1.7:1334
[Logging]
infologfile:silcd2.log:10000
:::1336:1
[AdminConnection]
-*:priikone:*:passwd:testi
+*:silc:silc:passwd:testi
[ServerConnection]
-212.146.42.253:passwd:priikone:1336:1:1
+10.2.1.7:passwd:priikone:1336:1:1
[RouterConnection]
-212.146.42.253:passwd:priikone:1335:1:1:0
+10.2.1.7:passwd:priikone:1333:1:1:0
[DenyConnection]
+
+[motd]
+./motd
The sender is performing an action and the message
is the indication of the action.
- 0x0008 - 0x0200 RESERVED
+ 0x0008 SILC_MESSAGE_FLAG_NOTICE
+
+ The message is for example and informational notice
+ type message.
+
+ 0x0010 - 0x0200 RESERVED
Reserved for future flags
Reply messages to the command:
Max Arguments: 14
- Arguments: (1) <Status Payload> (2) <channel>
- (3) <Channel ID> (4) <Client ID>
- (5) <channel mode mask> (6) <created>
- (7) <Channel Key Payload> (8) [<ban list>]
- (9) [<invite list>] (10) [<topic>]
- (11) [<hmac>] (12) <list count>
- (13) <Client ID list> (14) <client mode list>
+ Arguments: (1) <Status Payload> (2) <channel>
+ (3) <Channel ID> (4) <Client ID>
+ (5) <channel mode mask> (6) <created>
+ (7) [<Channel Key Payload>] (8) [<ban list>]
+ (9) [<invite list>] (10) [<topic>]
+ (11) [<hmac>] (12) <list count>
+ (13) <Client ID list> (14) <client mode list>
This command replies with the channel name requested by the
client, channel ID of the channel and topic of the channel
SILC_STATUS_ERR_NO_SERVER_PRIV
-
-
-
21 SILC_COMMAND_CLOSE
Max Arguments: 2
SILC_LOG_DEBUG(("Sending packet to channel"));
- if (!channel || !channel->hmac ||
- (!channel->channel_key && !key && !channel->private_keys)) {
- client->ops->say(client, conn,
- "Cannot talk to channel: key does not exist");
- return;
- }
-
/* Take the key to be used */
if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
if (key) {
hmac = channel->hmac;
}
+ if (!cipher || !hmac)
+ return;
+
/* Generate IV */
iv_len = silc_cipher_get_block_len(cipher);
if (channel->iv[0] == '\0')
silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
memset(hash, 0, sizeof(hash));
- /* Client is now joined to the channel */
- channel->on_channel = TRUE;
-
out:
silc_free(id);
silc_channel_key_payload_free(payload);
several private keys per one channel. In this case only some of the
clients on the channel may know the one key and only some the other key.
- if `cipher' and/or `hmac' is NULL then default values will be used
+ If `cipher' and/or `hmac' is NULL then default values will be used
(aes-256-cbc for cipher and hmac-sha1-96 for hmac).
The private key for channel is optional. If it is not set then the
{
SilcChannelPrivateKey entry;
unsigned char hash[32];
+ SilcSKEKeyMaterial *keymat;
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
return FALSE;
if (!silc_hmac_is_supported(hmac))
return FALSE;
+ /* 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)
+ != SILC_SKE_STATUS_OK)
+ return FALSE;
+
/* Remove the current key, if it exists. */
if (channel->channel_key) {
silc_cipher_free(channel->channel_key);
channel->key = NULL;
channel->key_len = 0;
}
- if (channel->hmac)
+ if (channel->hmac) {
silc_hmac_free(channel->hmac);
+ channel->hmac = NULL;
+ }
if (!channel->private_keys)
channel->private_keys = silc_dlist_init();
/* Save the key */
entry = silc_calloc(1, sizeof(*entry));
- entry->key = silc_calloc(key_len, sizeof(*entry->key));
- memcpy(entry->key, key, key_len);
- entry->key_len = key_len;
+ entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
+ memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
+ entry->key_len = keymat->enc_key_len / 8;
/* Allocate the cipher and set the key*/
silc_cipher_alloc(cipher, &entry->cipher);
- silc_cipher_set_key(entry->cipher, key, key_len * 8);
+ silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
/* Generate HMAC key from the channel key data and set it */
silc_hmac_alloc(hmac, NULL, &entry->hmac);
- silc_hash_make(entry->hmac->hash, key, key_len, hash);
+ silc_hash_make(entry->hmac->hash, entry->key, entry->key_len, hash);
silc_hmac_set_key(entry->hmac, hash, silc_hash_len(entry->hmac->hash));
memset(hash, 0, sizeof(hash));
if (!channel->curr_key)
channel->curr_key = entry;
+ /* Free the key material */
+ silc_ske_free_key_material(keymat);
+
return TRUE;
}
SILC_CLIENT_CMD_FUNC(restart)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
- SilcClientConnection conn = cmd->conn;
SilcBuffer buffer;
if (!cmd->conn) {
SilcChannelUser chu;
unsigned int argc, mode, len, list_count;
char *topic, *tmp, *channel_name = NULL, *hmac;
- SilcBuffer keyp, client_id_list, client_mode_list;
+ SilcBuffer keyp = NULL, client_id_list, client_mode_list;
int i;
SILC_LOG_DEBUG(("Start"));
/* Get channel key */
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
- if (!tmp) {
- silc_id_payload_free(idp);
- silc_free(channel_name);
- goto out;
+ if (tmp) {
+ keyp = silc_buffer_alloc(len);
+ silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
+ silc_buffer_put(keyp, tmp, len);
}
- keyp = silc_buffer_alloc(len);
- silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
- silc_buffer_put(keyp, tmp, len);
/* Get topic */
topic = silc_argument_get_arg_type(cmd->args, 10, NULL);
client_mode_list->head);
/* Save channel key */
- silc_client_save_channel_key(conn, keyp, channel);
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+ silc_client_save_channel_key(conn, keyp, channel);
+
+ /* Client is now joined to the channel */
+ channel->on_channel = TRUE;
/* Notify application */
- COMMAND_REPLY((ARGS, channel_name, channel, mode, 0, keyp->head, NULL,
+ COMMAND_REPLY((ARGS, channel_name, channel, mode, 0,
+ keyp ? keyp->head : NULL, NULL,
NULL, topic, hmac, list_count, client_id_list,
client_mode_list));
/* Execute any pending command callbacks */
SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
- silc_buffer_free(keyp);
+ if (keyp)
+ silc_buffer_free(keyp);
silc_buffer_free(client_id_list);
silc_buffer_free(client_mode_list);
#define SILC_MESSAGE_FLAG_AUTOREPLY 0x0001
#define SILC_MESSAGE_FLAG_NOREPLY 0x0002
#define SILC_MESSAGE_FLAG_ACTION 0x0004
-#define SILC_MESSAGE_FLAG_RESERVED 0x0008 /* to 0x0200 */
+#define SILC_MESSAGE_FLAG_NOTICE 0x0008
+#define SILC_MESSAGE_FLAG_RESERVED 0x0010 /* to 0x0200 */
#define SILC_MESSAGE_FLAG_PRIVATE 0x0400 /* to 0x8000 */
/* Prototypes */