+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
+ message to a channel with SILC_MESSAGE_FLAG_ACTION to indicate
+ some action. Affected file silc/local_command.[ch].
+
+ * Changed channel_message and private_message client operations
+ to deliver the message flags to the application. Added also
+ the `flags' arguments to the silc_client_send_channel_message
+ and silc_client_send_private_message functions. Affected file
+ silcapi.h.
+
Wed Mar 28 20:50:47 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Redefined the Private Message Payload to support private message
* Defined some of the message (for channel and private message)
flags. Updated the protocol specs and added the flags to the
- lib/silccore/silcchannel.h.
+ lib/silccore/silcchannel.h. The type is SilcMessageFlags.
Wed Mar 28 15:52:36 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
and port of the remote client's key agreement
server.
+ /ME <channel> <action message>
+
+ This command is used to send an action to the channel.
+ This equals to CTCP's ACTION (IRC's /ME) command.
Features
========
passphrase or public key that can be used in the authentication
when regaining the founder rights.
- o New packets and features in the packets
- (draft-riikonen-silc-pp-xx.txt):
-
- o Define the Private Message packet to include private message
- flags and define the flags. The flags could indicate whether
- the message is, for example autoreply or the receiver should not
- reply to the private messages. What other flags?
- o Define the Channel Message packet to include channel message
- flags and define the flags. Actually the flags should be same
- as for the private message flags. This way we can implement
- for example the CTCP style ACTION (/ME command) messages.
-
o New features in the KE/auth protocol
(draft-riikonen-silc-ke-auth-xx.txt):
received in the packet. The `channel_name' is the name of the channel. */
void silc_channel_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, SilcChannelEntry channel
- , char *msg)
+ SilcClientEntry sender, SilcChannelEntry channel,
+ SilcMessageFlags flags, char *msg)
{
/* Message from client */
if (conn && !strcmp(conn->current_channel->channel_name,
channel->channel_name))
- silc_print(client, "<%s> %s", sender ? sender->nickname : "[<unknown>]",
- msg);
+ if (flags & SILC_MESSAGE_FLAG_ACTION)
+ silc_print(client, "* %s %s", sender ? sender->nickname : "[<unknown>]",
+ msg);
+ else
+ silc_print(client, "<%s> %s", sender ? sender->nickname : "[<unknown>]",
+ msg);
else
- silc_print(client, "<%s:%s> %s", sender ? sender->nickname : "[<unknown>]",
- channel->channel_name, msg);
+ if (flags & SILC_MESSAGE_FLAG_ACTION)
+ silc_print(client, "* %s:%s %s", sender ? sender->nickname :
+ "[<unknown>]",
+ channel->channel_name, msg);
+ else
+ silc_print(client, "<%s:%s> %s", sender ? sender->nickname :
+ "[<unknown>]",
+ channel->channel_name, msg);
}
/* Private message to the client. The `sender' is the nickname of the
sender received in the packet. */
void silc_private_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, char *msg)
+ SilcClientEntry sender, SilcMessageFlags flags,
+ char *msg)
{
silc_print(client, "*%s* %s", sender->nickname, msg);
}
void silc_say(SilcClient client, SilcClientConnection conn, char *msg, ...);
void silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender,
- SilcChannelEntry channel, char *msg);
+ SilcChannelEntry channel,
+ SilcMessageFlags flags, char *msg);
void silc_private_message(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, char *msg);
+ SilcClientEntry sender,
+ SilcMessageFlags flags, char *msg);
void silc_notify(SilcClient client, SilcClientConnection conn,
SilcNotifyType type, ...);
void silc_command(SilcClient client, SilcClientConnection conn,
SILC_CLIENT_LCMD(msg, MSG, "MSG", 0, 3),
SILC_CLIENT_LCMD(away, AWAY, "AWAY", 0, 2),
SILC_CLIENT_LCMD(key, KEY, "KEY", 0, 7),
+ SILC_CLIENT_LCMD(me, ME, "ME", 0, 3),
{ NULL, 0, NULL, 0, 0 },
};
silc_print(client, "-> *%s* %s", cmd->argv[1], cmd->argv[2]);
/* Send the private message */
- silc_client_send_private_message(client, conn, client_entry,
+ silc_client_send_private_message(client, conn, client_entry, 0,
cmd->argv[2], cmd->argv_lens[2],
TRUE);
silc_free(server);
silc_client_command_free(cmd);
}
+
+/* Sends an action to the channel. Equals CTCP's ACTION (IRC's /ME)
+ command. */
+
+SILC_CLIENT_LCMD_FUNC(me)
+{
+ 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_ACTION,
+ 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_MSG 5
#define SILC_LOCAL_COMMAND_AWAY 6
#define SILC_LOCAL_COMMAND_KEY 7
+#define SILC_LOCAL_COMMAND_ME 8
/* Macros */
SILC_CLIENT_LCMD_FUNC(server);
SILC_CLIENT_LCMD_FUNC(away);
SILC_CLIENT_LCMD_FUNC(key);
+SILC_CLIENT_LCMD_FUNC(me);
#endif
silc_client_send_channel_message(app->client,
app->conn,
app->conn->current_channel, NULL,
- data, strlen(data), TRUE);
+ 0, data, strlen(data), TRUE);
}
}
sock->type == SILC_SOCKET_TYPE_ROUTER &&
!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
SilcBuffer chp;
- unsigned int iv_len, i, data_len;
+ unsigned int iv_len, i;
+ unsigned short data_len, flags;
iv_len = silc_cipher_get_block_len(channel->channel_key);
if (channel->iv[0] == '\0')
silc_hash_make(server->md5hash, channel->iv, iv_len, channel->iv);
/* Encode new payload. This encrypts it also. */
- SILC_GET16_MSB(data_len, packet->buffer->data);
- chp = silc_channel_message_payload_encode(data_len,
- packet->buffer->data + 2,
+ SILC_GET16_MSB(flags, packet->buffer->data);
+ SILC_GET16_MSB(data_len, packet->buffer->data + 2);
+ chp = silc_channel_message_payload_encode(flags, data_len,
+ packet->buffer->data + 4,
iv_len, channel->iv,
channel->channel_key,
- channel->hmac, server->rng);
+ channel->hmac);
silc_buffer_put(packet->buffer, chp->data, chp->len);
silc_buffer_free(chp);
}
/* Get authentication data */
silc_buffer_pull(ctx->packet->buffer, 4);
ret = silc_buffer_unformat(ctx->packet->buffer,
- SILC_STR_UI_XNSTRING(&auth_data,
- payload_len),
+ SILC_STR_UI_XNSTRING_ALLOC(&auth_data,
+ payload_len),
SILC_STR_END);
if (ret == -1) {
SILC_LOG_DEBUG(("Bad payload in authentication packet"));
/* Authentication failed */
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
SILC_LOG_DEBUG(("No configuration for remote connection"));
SILC_LOG_ERROR(("Remote connection not configured"));
SILC_LOG_ERROR(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
/* Authentication failed */
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
return;
break;
-
+
case SILC_AUTH_PUBLIC_KEY:
/* Public key authentication */
SILC_LOG_DEBUG(("Public key authentication"));
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
+ silc_free(auth_data);
return;
}
}
/* Authentication failed */
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
if (ret)
break;
-
+
SILC_LOG_ERROR(("Authentication failed"));
SILC_LOG_DEBUG(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
SILC_LOG_DEBUG(("No configuration for remote connection"));
SILC_LOG_ERROR(("Remote connection not configured"));
SILC_LOG_ERROR(("Authentication failed"));
+ silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
protocol->execute(server->timeout_queue, 0,
protocol, fd, 0, 300000);
}
}
+ silc_free(auth_data);
+
/* Save connection type. This is later used to create the
ID for the connection. */
ctx->conn_type = conn_type;
[Cipher]
-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
+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
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:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
[ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
[Logging]
infologfile:silcd2.log:10000
:::1336:1
[AdminConnection]
-*:silc:silc:passwd:testi
+*:priikone:*:passwd:testi
[ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1336:1:1
[RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
[DenyConnection]
-
-[motd]
-./motd
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Message Length | |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| Flags | Message Length |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Message Data ~
| |
.in 6
+o Flags (2 bytes) - Includes the flags of the channel
+ messages. The flags can indicate a reason or purpose
+ for the channel message. Note, that the Private Message
+ Payload use these same flags for the same purpose. The
+ following flags are defined:
+
+ 0x0000 SILC_MESSAGE_FLAG_NONE
+
+ No specific flags set.
+
+ 0x0001 SILC_MESSAGE_FLAG_AUTREPLY
+
+ This message is an automatic reply to a earlier
+ received message.
+
+ 0x0002 SILC_MESSAGE_FLAG_NOREPLY
+
+ There should not be reply messages to this
+ message.
+
+ 0x0004 SILC_MESSAGE_FLAG_ACTION
+
+ The sender is performing an action and the message
+ is the indication of the action.
+
+ 0x0008 - 0x0200 RESERVED
+
+ Reserved for future flags
+
+ 0x0400 - 0x8000 PRIVATE RANGE
+
+ Private range for free use.
+
o Message Length (2 bytes) - Indicates the length of the
the Message Data field in the payload, not including any
other field.
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Nickname Length | |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| Flags | Nickname Length |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Nickname ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Flags | Message Data Length |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Message Data Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
~ Message Data ~
| |
.in 6
+o Flags (2 bytes) - This field includes the flags of the
+ private message. They can indicate a different reason or
+ purpose for the private message. See the section 2.3.9
+ Channel Message Payload for defined flags. Note, that
+ the Channel Message Payload use the same flags for the
+ same purpose.
+
o Nickname Length (2 bytes) - Indicates the length of the
Nickname field, not including any other field.
to the Client ID in the SILC Packet Header. This nickname
is merely provided to be displayed by the client.
-o Flags (2 bytes) - This field includes the flags of the
- private message. They can indicate a different reason or
- purpose for the private message. See section XXX for the
- defined flags.
-
o Message Data Length (2 bytes) - Indicates the length of the
Message Data field, not includes any other field.
SilcClientConnection conn,
SilcChannelEntry channel,
SilcChannelPrivateKey key,
+ SilcMessageFlags flags,
unsigned char *data,
unsigned int data_len,
int force_send)
silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
/* Encode the channel payload. This also encrypts the message payload. */
- payload = silc_channel_message_payload_encode(0, data_len, data, iv_len,
+ payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
channel->iv, cipher, hmac);
/* Get data used in packet header encryption, keys and stuff. */
/* Pass the message to application */
client->ops->channel_message(client, conn, found ? chu->client : NULL,
- channel, message);
+ channel,
+ silc_channel_message_get_flags(payload),
+ message);
out:
if (id)
void silc_client_send_private_message(SilcClient client,
SilcClientConnection conn,
SilcClientEntry client_entry,
+ SilcMessageFlags flags,
unsigned char *data,
unsigned int data_len,
int force_send)
SILC_LOG_DEBUG(("Sending private message"));
/* Encode private message payload */
- buffer = silc_private_message_payload_encode(0, strlen(conn->nickname),
+ buffer = silc_private_message_payload_encode(flags, strlen(conn->nickname),
conn->nickname,
data_len, data,
client_entry->send_key);
}
/* Pass the private message to application */
- client->ops->private_message(client, conn, remote_client,
+ client->ops->private_message(client, conn, remote_client,
+ silc_private_message_get_flags(payload),
silc_private_message_get_message(payload,
NULL));
/* Send the away message */
silc_client_send_private_message(client, conn, remote_client,
+ SILC_MESSAGE_FLAG_AUTOREPLY,
conn->away->away,
strlen(conn->away->away), TRUE);
}
The `channel' is the channel. */
void (*channel_message)(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
- char *msg);
+ SilcMessageFlags flags, char *msg);
/* Private message to the client. The `sender' is the sender of the
message. */
void (*private_message)(SilcClient client, SilcClientConnection conn,
- SilcClientEntry sender, char *msg);
+ SilcClientEntry sender, SilcMessageFlags flags,
+ char *msg);
/* Notify message to the client. The notify arguments are sent in the
same order as servers sends them. The arguments are same as received
SilcClientConnection conn,
SilcChannelEntry channel,
SilcChannelPrivateKey key,
+ SilcMessageFlags flags,
unsigned char *data,
unsigned int data_len,
int force_send);
void silc_client_send_private_message(SilcClient client,
SilcClientConnection conn,
SilcClientEntry client_entry,
+ SilcMessageFlags flags,
unsigned char *data,
unsigned int data_len,
int force_send);
silc_free(payload);
}
+/* Return flags */
+
+unsigned short
+silc_channel_message_get_flags(SilcChannelMessagePayload payload)
+{
+ return payload->flags;
+}
+
/* Return data */
unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload,
SilcCipher cipher,
SilcHmac hmac);
void silc_channel_message_payload_free(SilcChannelMessagePayload payload);
+unsigned short
+silc_channel_message_get_flags(SilcChannelMessagePayload payload);
unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload,
unsigned int *data_len);
unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload);
/* Private Message Payload structure. Contents of this structure is parsed
from SILC packets. */
struct SilcPrivateMessagePayloadStruct {
+ unsigned short flags;
unsigned short nickname_len;
unsigned char *nickname;
- unsigned short flags;
unsigned short message_len;
unsigned char *message;
};
/* Parse the Private Message Payload. Ignore the padding. */
ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&new->flags),
SILC_STR_UI16_NSTRING_ALLOC(&new->nickname,
&new->nickname_len),
- SILC_STR_UI_SHORT(&new->flags),
SILC_STR_UI16_NSTRING_ALLOC(&new->message,
&new->message_len),
SILC_STR_END);
the cipher is provided the packet is also encrypted here. It is provided
if the private message private keys are used. */
-SilcBuffer silc_private_message_payload_encode(unsigned int nickname_len,
+SilcBuffer silc_private_message_payload_encode(unsigned short flags,
+ unsigned int nickname_len,
unsigned char *nickname,
- unsigned short flags,
unsigned short data_len,
unsigned char *data,
SilcCipher cipher)
SILC_LOG_DEBUG(("Encoding private message payload"));
- len = 2 + nickname_len + 4 + data_len;
+ len = 4 + nickname_len + 2 + data_len;
if (cipher) {
/* Calculate length of padding. */
/* Encode the Channel Message Payload */
silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(flags),
SILC_STR_UI_SHORT(nickname_len),
SILC_STR_UI_XNSTRING(nickname, nickname_len),
- SILC_STR_UI_SHORT(flags),
SILC_STR_UI_SHORT(data_len),
SILC_STR_UI_XNSTRING(data, data_len),
SILC_STR_UI_XNSTRING(pad, pad_len),
silc_free(payload);
}
+/* Return flags */
+
+unsigned short
+silc_private_message_get_flags(SilcPrivateMessagePayload payload)
+{
+ return payload->flags;
+}
+
/* Return nickname */
unsigned char *
return payload->message;
}
-
-/* Return flags */
-
-unsigned short
-silc_private_message_get_flags(SilcPrivateMessagePayload payload)
-{
- return payload->flags;
-}
SilcPrivateMessagePayload
silc_private_message_payload_parse(SilcBuffer buffer, SilcCipher cipher);
-SilcBuffer silc_private_message_payload_encode(unsigned int nickname_len,
+SilcBuffer silc_private_message_payload_encode(unsigned short flags,
+ unsigned int nickname_len,
unsigned char *nickname,
- unsigned short flags,
unsigned short data_len,
unsigned char *data,
SilcCipher cipher);
void silc_private_message_payload_free(SilcPrivateMessagePayload payload);
+unsigned short
+silc_private_message_get_flags(SilcPrivateMessagePayload payload);
unsigned char *
silc_private_message_get_nickname(SilcPrivateMessagePayload payload,
unsigned int *nickname_len);
unsigned char *
silc_private_message_get_message(SilcPrivateMessagePayload payload,
unsigned int *message_len);
-unsigned short
-silc_private_message_get_flags(SilcPrivateMessagePayload payload);
#endif