From aab72291cf0379050d3b327b43f366d7e886d7c8 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 3 Apr 2002 18:27:43 +0000 Subject: [PATCH] Started implementing protocol version 1.1 and narrowing down TODO list, see CHANGES. --- CHANGES | 73 ++++ TODO | 45 --- apps/irssi/docs/help/in/cmode.in | 6 + .../irssi/src/fe-common/silc/module-formats.c | 8 +- apps/irssi/src/silc/core/client_ops.c | 19 +- apps/irssi/src/silc/core/client_ops.h | 8 +- apps/silcd/command.c | 371 +++++++++--------- apps/silcd/command.h | 10 +- apps/silcd/idlist.c | 11 +- apps/silcd/idlist.h | 2 +- apps/silcd/packet_receive.c | 85 ++-- apps/silcd/packet_send.c | 23 +- apps/silcd/packet_send.h | 6 +- apps/silcd/protocol.c | 62 +-- apps/silcd/server_util.c | 22 ++ doc/draft-riikonen-silc-commands-03.nroff | 145 +++---- doc/draft-riikonen-silc-pp-05.nroff | 31 +- doc/draft-riikonen-silc-spec-05.nroff | 6 +- doc/example_silcd.conf.in | 4 +- lib/silcclient/client_channel.c | 25 +- lib/silcclient/client_notify.c | 159 +++++--- lib/silcclient/client_ops_example.c | 7 +- lib/silcclient/client_prvmsg.c | 9 +- lib/silcclient/command.c | 268 +++++++------ lib/silcclient/command_reply.c | 145 ++++--- lib/silcclient/silcclient.h | 7 +- lib/silccore/silcchannel.h | 6 +- lib/silccore/silccommand.h | 8 +- lib/silccore/silcmode.h | 2 + lib/silcutil/silcutil.c | 6 + prepare | 2 +- 31 files changed, 895 insertions(+), 686 deletions(-) diff --git a/CHANGES b/CHANGES index a372c867..299db091 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,76 @@ +Wed Apr 3 16:24:51 EEST 2002 Pekka Riikonen + + * Upgraded the protocol version to 1.1, updated protocol specs + and software. + + * Added the nickname as new argument to NICK_CHANGE notify and + added it to protocol specs and implemented it to client and + server. Protocol TODO #3. Affected files are silcd/idlist.[ch], + silcd/command.c, silcd/packet_receive.c, packet_send.[ch], and + lib/silcclient/client_notify.c. + + * Added the killer's client ID to the KILLED notify and added + it to protocol specs and implemented it to client and server. + Protocol TODO #13. Affected files are silcd/command.c, + silcd/packet_receive.c, packet_send.[ch], + lib/silcclient/client_notify.c, irssi/src/silc/core/client_ops.c. + The killer's client entry is now returned to application in + the `notify' client operation. + + * Fixed the Max Argument fields that had too large value set + in the protocol specs. Protocol TODO #14. + + * Added the LEAVE command reply to return the ID of parted + channel. Updated protocol specs and implemented it to the + client and server. Protocol TODO #15. Affected files are + silcd/command.c, lib/silcclient/command_reply.c. The channel + entry is now returned to application in the `command_reply' + client operation. + + * Rewrote the version SKE version checking in client libary + and in server to use the silc_parse_version_string. Affected + files are lib/silcclient/protocol.c, silcd/protocol.c. + + * Added SILC_STATUS_ERR_NO_CHANNEL_FOPRIV error status to few + commands that was missing it, and updated protocol specs and + the server implementation. Protocol TODO #10. The affected + file is silcd/command.c. + + * Defined new message flags SILC_MESSAGE_FLAG_REPLY to be + generic reply to a generic request (REQUEST flag), and + SILC_MESSAGE_FLAG_DATA to send any kind of data in a generic + way. A draft-riikonen-silc-flags-payloads-00.txt is written + to define the payload for DATA flag. Added the flags to + the implementation. Protocol TODO #9. Affected file is + lib/silccore/silcchannel.h. + + Changed the client library to return the message length + to application as well in the channel_message and private_message + client operations. Affected files are + lib/silcclient/client_prvmsg, lib/silcclient/client_channel.c, + lib/silcclient/silcclient.h, irssi/src/silc/core/client_ops.c, + and lib/silcclient/client_ops_example.c. + + * Added two new channel modes: SILC_CMODE_SILENCE_USERS + and SILC_CMODE_SILENCE_OPERS which can be used to moderate + the channel. Updated protocol specs and impelemented this + to client and server. Protocol TODO #6. Affected files are + silcd/packet_receive.c, server_util.c, lib/silcclient/command.c, + lib/silcclient/client_channel.c, lib/silccore/silcmode.h. + + Added new options m and M to CMODE command in Irssi SILC + client to set these modes. + + * Deprecated all administrative commands from SILC protocol + since they are highly implementation specific commands. + Updated protocol specs. Moved the old commands in + implementations to private range of command types. Affected + files are silcd/command.c, lib/silcclient/command.c and + lib/silcclient/command_reply.c. Protocol TODO #8. + + * Fixed a bug in server where sending unknown command crashes + the server. Affected file silcd/command.c. + Wed Apr 3 09:57:47 CEST 2002 Pekka Riikonen * Added SILC_PROTOCOLVERSION macro to check protocol version diff --git a/TODO b/TODO index d7ff4d8e..7c8615e5 100644 --- a/TODO +++ b/TODO @@ -16,10 +16,6 @@ TODO/bugs In SILC Client Library o Additions to do after protocol version 1.1: - o Fix the NICK_CHANGE notify handling not to create new entry - for the changed client, but take the nickname from the notify - (removes need for resolving as well). Protocol TODO entry 3. - o Add support for list of errors in command replies. Protocol TODO entry 1. @@ -44,7 +40,6 @@ TODO/bugs In SILC Server o JOIN (check that joining is allowed) o SIGNOFF (maybe should check that notifier owns the client) - o KILLED (check that killling is allowed (Protocol TODO #13)) o Backup router related issues (Fix this to 1.0): @@ -128,13 +123,6 @@ describe new stuff to be added to protocol versions 1.x. *after* sending successfully found entries (this way receiver may ignore them). To be included in protocol version 1.1. - 3. Define the NICK_CHANGE notify to send the changed nickname as a new - third argument. This will make the NICK_CHANGE notify handling easier - in the receiver's end (client primarily) since it removes the - requirement that receiver must resolve (using IDENTIFY or WHOIS) the - new Client ID received in the notify (because of the new nickname is - unknown). To be included in protocol version 1.1. - 4. Add "request parameters" or similar to the WHOIS command, which can be used to request various parameters (something not returned by standard WHOIS command) about clients (info that could be fetched @@ -148,10 +136,6 @@ describe new stuff to be added to protocol versions 1.x. 5. Inviting and banning by public key should be made possible. To be included in protocol version 1.x. - 6. Add perhaps SILENCE_USERS, SILENCE_OPERS channel user modes which - can be used to silence (moderate) normal users and opers (this set - only by founder). To be included in protocol version 1.1. - 7. Channel Message Payload needs slight redesining to include the IV field to the MAC generation of the payload. It is authenticated by the packet's MAC but not by the payload's MAC. Since the IV @@ -159,40 +143,11 @@ describe new stuff to be added to protocol versions 1.x. payload MAC and not alone by packet MAC. To be included in protocol version 1.1. - 8. Remove the administrative commands from the protocol all together. - It does not make sense for the protocol to define how a server is - reconnected or shutdown, since they are implementation and - configuration issues. Besides protocol provides only limited set of - administrative commands and cannot define all that one could imagine. - To be included in protocol version 1.1. - - 9. Add SILC_MESAGE_FLAG_REPLY for being other side to the - SILC_MESSAGE_FLAG_REQUEST. Add generic SILC_MESSAGE_FLAG_DATA, which - can include generic payload, which can include generic data. The - payload definition is left out for now. To be included in protocol - version 1.1. - - 10. Check command reply error status types in various commands, - specifically NO_FOPRIV is missing from many commands. To be - included in protocol version 1.1. - 11. Change the wording in Private Message Key Payload definition to describe the problems of trusting the payload, and to indicate that the receiver may not accept the key in the payload, and to describe other means of distributing a key. - 13. Add the killer's client ID to the KILLED notify. To be included in - protocol version 1.1. - - 14. The length of Arguments Num field in Notify Payload and Command - Payload enforces that total of 256 arguments can be associated - to a such payload. However, command-xx draft specified much higher - values, and these should be fixed. - - 15. The LEAVE command reply should return the Channel ID of the channel - that was parted. - 16. Add STATS command after all to the protocol for providing practically same information client gets when connects to a server. Normal server would send this to router always when received from client. - diff --git a/apps/irssi/docs/help/in/cmode.in b/apps/irssi/docs/help/in/cmode.in index 4370809e..b9e49b81 100644 --- a/apps/irssi/docs/help/in/cmode.in +++ b/apps/irssi/docs/help/in/cmode.in @@ -13,6 +13,12 @@ option(s). The following modes are available: i Set/unset channel as invite only channel t Set/unset that only channel operator or founder may set channel topic + m Set/unset user silencing. Normal users + are not able to talk on channel. Only + channel founder may set this mode + M Set/unset operator silencing. Operators + are not able to talk on channel. Only + channel founder may set this mode l Set/unset channel's user limit a Set/unset passphrase for channel that must be provided when joining to the channel. diff --git a/apps/irssi/src/fe-common/silc/module-formats.c b/apps/irssi/src/fe-common/silc/module-formats.c index 6ac3306f..a8861329 100644 --- a/apps/irssi/src/fe-common/silc/module-formats.c +++ b/apps/irssi/src/fe-common/silc/module-formats.c @@ -43,10 +43,10 @@ FORMAT_REC fecommon_silc_formats[] = { { "ban_list", "channel {channel $0} ban list: $1", 2, { 0, 0 } }, { "no_ban_list", "channel {channel $0} ban list not set", 1, { 0 } }, { "inviting", "Inviting {nick $0} to channel {channel $1}", 2, { 0, 0 } }, - { "kicked_you", "You have been kicked off channel {channel $0} by {nick $1} ($2)", 3, { 0, 0 } }, - { "kicked", "{nick $0} has been kicked off channel {channel $1} by {nick $2} ($3)", 4, { 0, 0, 0 } }, - { "killed_you", "You have been killed from the SILC Network", 0 }, - { "killed", "{nick $0} has been killed from the SILC Network ($1)", 2, { 0, 0 } }, + { "kicked_you", "You have been kicked off channel {channel $0} by {nick $1} ($2)", 3, { 0, 0, 0 } }, + { "kicked", "{nick $0} has been kicked off channel {channel $1} by {nick $2} ($3)", 4, { 0, 0, 0, 0 } }, + { "killed_you", "You have been killed from the SILC Network by {nick $0} ($1)", 2, { 0, 0 } }, + { "killed", "{nick $0} has been killed from the SILC Network by {nick $1} ($2)", 3, { 0, 0, 0 } }, /* WHOIS, WHOWAS and USERS (alias WHO) messages */ { NULL, "Who Queries", 0 }, diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 14699048..a4008b78 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -81,7 +81,8 @@ void silc_say_error(char *msg, ...) void silc_channel_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, - SilcMessageFlags flags, char *msg) + SilcMessageFlags flags, const unsigned char *message, + SilcUInt32 message_len) { SILC_SERVER_REC *server; SILC_NICK_REC *nick; @@ -89,7 +90,7 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, SILC_LOG_DEBUG(("Start")); - if (!msg) + if (!message) return; server = conn == NULL ? NULL : conn->context; @@ -108,13 +109,13 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, if (flags & SILC_MESSAGE_FLAG_ACTION) printformat_module("fe-common/silc", server, channel->channel_name, MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, - nick == NULL ? "[]" : nick->nick, msg); + nick == NULL ? "[]" : nick->nick, message); else if (flags & SILC_MESSAGE_FLAG_NOTICE) printformat_module("fe-common/silc", server, channel->channel_name, MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, - nick == NULL ? "[]" : nick->nick, msg); + nick == NULL ? "[]" : nick->nick, message); else - signal_emit("message public", 6, server, msg, + signal_emit("message public", 6, server, message, nick == NULL ? "[]" : nick->nick, nick == NULL ? "" : nick->host == NULL ? "" : nick->host, chanrec->name, nick); @@ -125,7 +126,8 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, void silc_private_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessageFlags flags, - char *msg) + const unsigned char *message, + SilcUInt32 message_len) { SILC_SERVER_REC *server; char userhost[256]; @@ -137,7 +139,7 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, if (sender->username) snprintf(userhost, sizeof(userhost) - 1, "%s@%s", sender->username, sender->hostname); - signal_emit("message private", 4, server, msg, + signal_emit("message private", 4, server, message, sender->nickname ? sender->nickname : "[]", sender->username ? userhost : NULL); } @@ -516,10 +518,12 @@ void silc_notify(SilcClient client, SilcClientConnection conn, client_entry = va_arg(va, SilcClientEntry); tmp = va_arg(va, char *); + client_entry2 = va_arg(va, SilcClientEntry); if (client_entry == conn->local_entry) { printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, + client_entry2 ? client_entry2->nickname : "", tmp ? tmp : ""); } else { list1 = nicklist_get_same_unique(SERVER(server), client_entry); @@ -533,6 +537,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn, printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, client_entry->nickname, + client_entry2 ? client_entry2->nickname : "", tmp ? tmp : ""); } break; diff --git a/apps/irssi/src/silc/core/client_ops.h b/apps/irssi/src/silc/core/client_ops.h index 69682f69..f7031fdb 100644 --- a/apps/irssi/src/silc/core/client_ops.h +++ b/apps/irssi/src/silc/core/client_ops.h @@ -27,10 +27,14 @@ void silc_say_error(char *msg, ...); void silc_channel_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, - SilcMessageFlags flags, char *msg); + SilcMessageFlags flags, + const unsigned char *message, + SilcUInt32 message_len); void silc_private_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, - SilcMessageFlags flags, char *msg); + SilcMessageFlags flags, + const unsigned char *message, + SilcUInt32 message_len); void silc_notify(SilcClient client, SilcClientConnection conn, SilcNotifyType type, ...); void silc_command(SilcClient client, SilcClientConnection conn, diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 7000a9ad..ba345af6 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -56,8 +56,6 @@ SilcServerCommand silc_command_list[] = SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(connect, CONNECT, - SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG), @@ -67,16 +65,19 @@ SilcServerCommand silc_command_list[] = SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG), - SILC_SERVER_CMD(close, CLOSE, - SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), - SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | - SILC_CF_OPER), SILC_SERVER_CMD(silcoper, SILCOPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER), SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(connect, PRIV_CONNECT, + SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), + SILC_SERVER_CMD(close, PRIV_CLOSE, + SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), + SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | + SILC_CF_OPER), + { NULL, 0 }, }; @@ -205,7 +206,7 @@ void silc_server_command_process(SilcServer server, if (cmd->cmd == command) break; - if (cmd == NULL) { + if (!cmd || !cmd->cb) { silc_server_command_send_status_reply(ctx, command, SILC_STATUS_ERR_UNKNOWN_COMMAND); silc_server_command_free(ctx); @@ -2027,7 +2028,7 @@ SILC_SERVER_CMD_FUNC(nick) silc_server_send_notify_nick_change(server, server->router->connection, server->server_type == SILC_SERVER ? FALSE : TRUE, client->id, - new_id); + new_id, nick); oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); @@ -2051,9 +2052,11 @@ SILC_SERVER_CMD_FUNC(nick) /* Send NICK_CHANGE notify to the client's channels */ silc_server_send_notify_on_channels(server, NULL, client, - SILC_NOTIFY_TYPE_NICK_CHANGE, 2, + SILC_NOTIFY_TYPE_NICK_CHANGE, 3, oidp->data, oidp->len, - nidp->data, nidp->len); + nidp->data, nidp->len, + client->nickname, + strlen(client->nickname)); send_reply: /* Send the new Client ID as reply command back to client */ @@ -2671,6 +2674,7 @@ SILC_SERVER_CMD_FUNC(kill) SilcClientID *client_id; unsigned char *tmp, *comment; SilcUInt32 tmp_len, tmp_len2; + SilcBuffer killer; bool local; SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2); @@ -2724,7 +2728,7 @@ SILC_SERVER_CMD_FUNC(kill) /* Get comment */ comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2); if (tmp_len2 > 128) - comment = NULL; + tmp_len2 = 128; /* Send reply to the sender */ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, @@ -2737,22 +2741,24 @@ SILC_SERVER_CMD_FUNC(kill) /* Send KILLED notify to the channels. It is not sent to the client as it will be sent differently destined directly to the client and not to the channel. */ + killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT); silc_server_send_notify_on_channels(server, remote_client, remote_client, SILC_NOTIFY_TYPE_KILLED, - comment ? 2 : 1, - tmp, tmp_len, - comment, comment ? tmp_len2 : 0); + 3, tmp, tmp_len, + comment, comment ? tmp_len2 : 0, + killer->data, killer->len); + silc_buffer_free(killer); /* Send KILLED notify to primary route */ if (!server->standalone) silc_server_send_notify_killed(server, server->router->connection, TRUE, - remote_client->id, comment); + remote_client->id, comment, client->id); /* Send KILLED notify to the client directly */ silc_server_send_notify_killed(server, remote_client->connection ? remote_client->connection : remote_client->router->connection, FALSE, - remote_client->id, comment); + remote_client->id, comment, client->id); /* Remove the client from all channels. This generates new keys to the channels as well. */ @@ -3748,7 +3754,9 @@ SILC_SERVER_CMD_FUNC(cmode) /* Check that client has rights to change any requested channel modes */ if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, - SILC_STATUS_ERR_NO_CHANNEL_PRIV); + (chl->mode == 0 ? + SILC_STATUS_ERR_NO_CHANNEL_PRIV : + SILC_STATUS_ERR_NO_CHANNEL_FOPRIV)); goto out; } @@ -4173,7 +4181,7 @@ SILC_SERVER_CMD_FUNC(cumode) but themselves. */ if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE, - SILC_STATUS_ERR_NO_CHANNEL_PRIV); + SILC_STATUS_ERR_NO_CHANNEL_FOPRIV); goto out; } @@ -4638,61 +4646,6 @@ SILC_SERVER_CMD_FUNC(silcoper) silc_server_command_free(cmd); } -/* Server side command of CONNECT. Connects us to the specified remote - server or router. */ - -SILC_SERVER_CMD_FUNC(connect) -{ - SilcServerCommandContext cmd = (SilcServerCommandContext)context; - SilcServer server = cmd->server; - SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; - unsigned char *tmp, *host; - SilcUInt32 tmp_len; - SilcUInt32 port = SILC_PORT; - - SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2); - - if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) - goto out; - - /* Check whether client has the permissions. */ - if (client->mode == SILC_UMODE_NONE) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT, - SILC_STATUS_ERR_NO_SERVER_PRIV); - goto out; - } - - if (server->server_type == SILC_ROUTER && - client->mode & SILC_UMODE_SERVER_OPERATOR) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT, - SILC_STATUS_ERR_NO_ROUTER_PRIV); - goto out; - } - - /* Get the remote server */ - host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); - if (!host) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT, - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); - goto out; - } - - /* Get port */ - tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); - if (tmp) - SILC_GET32_MSB(port, tmp); - - /* Create the connection. It is done with timeout and is async. */ - silc_server_create_connection(server, host, port); - - /* Send reply to the sender */ - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT, - SILC_STATUS_OK); - - out: - silc_server_command_free(cmd); -} - /* Server side of command BAN. This is used to manage the ban list of the channel. To add clients and remove clients from the ban list. */ @@ -4816,111 +4769,6 @@ SILC_SERVER_CMD_FUNC(ban) silc_server_command_free(cmd); } -/* Server side command of CLOSE. Closes connection to a specified server. */ - -SILC_SERVER_CMD_FUNC(close) -{ - SilcServerCommandContext cmd = (SilcServerCommandContext)context; - SilcServer server = cmd->server; - SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; - SilcServerEntry server_entry; - SilcSocketConnection sock; - unsigned char *tmp; - SilcUInt32 tmp_len; - unsigned char *name; - SilcUInt32 port = SILC_PORT; - - SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2); - - if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) - goto out; - - /* Check whether client has the permissions. */ - if (client->mode == SILC_UMODE_NONE) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE, - SILC_STATUS_ERR_NO_SERVER_PRIV); - goto out; - } - - /* Get the remote server */ - name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); - if (!name) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE, - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); - goto out; - } - - /* Get port */ - tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); - if (tmp) - SILC_GET32_MSB(port, tmp); - - server_entry = silc_idlist_find_server_by_conn(server->local_list, - name, port, FALSE, NULL); - if (!server_entry) - server_entry = silc_idlist_find_server_by_conn(server->global_list, - name, port, FALSE, NULL); - if (!server_entry) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE, - SILC_STATUS_ERR_NO_SERVER_ID); - goto out; - } - - /* Send reply to the sender */ - silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE, - SILC_STATUS_OK); - - /* Close the connection to the server */ - sock = (SilcSocketConnection)server_entry->connection; - - /* If we shutdown primary router connection manually then don't trigger - any reconnect or backup router connections, by setting the router - to NULL here. */ - if (server->router == server_entry) { - server->id_entry->router = NULL; - server->router = NULL; - server->standalone = TRUE; - } - silc_server_free_sock_user_data(server, sock, NULL); - silc_server_close_connection(server, sock); - - out: - silc_server_command_free(cmd); -} - -/* Server side command of SHUTDOWN. Shutdowns the server and closes all - active connections. */ - -SILC_SERVER_CMD_FUNC(shutdown) -{ - SilcServerCommandContext cmd = (SilcServerCommandContext)context; - SilcServer server = cmd->server; - SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; - - SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0); - - if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) - goto out; - - /* Check whether client has the permission. */ - if (client->mode == SILC_UMODE_NONE) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN, - SILC_STATUS_ERR_NO_SERVER_PRIV); - goto out; - } - - /* Send reply to the sender */ - silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN, - SILC_STATUS_OK); - - /* Then, gracefully, or not, bring the server down. */ - silc_server_stop(server); - exit(0); - - out: - silc_server_command_free(cmd); -} - /* Server side command of LEAVE. Removes client from a channel. */ SILC_SERVER_CMD_FUNC(leave) @@ -4975,8 +4823,8 @@ SILC_SERVER_CMD_FUNC(leave) server->server_type == SILC_ROUTER ? TRUE : FALSE, channel, id_entry->id); - silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE, - SILC_STATUS_OK); + silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE, + SILC_STATUS_OK, 2, tmp, len); /* Remove client from channel */ if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry, @@ -5333,3 +5181,166 @@ SILC_SERVER_CMD_FUNC(getkey) silc_free(server_id); silc_server_command_free(cmd); } + + +/* Private range commands, specific to this implementation */ + +/* Server side command of CONNECT. Connects us to the specified remote + server or router. */ + +SILC_SERVER_CMD_FUNC(connect) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; + unsigned char *tmp, *host; + SilcUInt32 tmp_len; + SilcUInt32 port = SILC_PORT; + + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2); + + if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) + goto out; + + /* Check whether client has the permissions. */ + if (client->mode == SILC_UMODE_NONE) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT, + SILC_STATUS_ERR_NO_SERVER_PRIV); + goto out; + } + + if (server->server_type == SILC_ROUTER && + client->mode & SILC_UMODE_SERVER_OPERATOR) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT, + SILC_STATUS_ERR_NO_ROUTER_PRIV); + goto out; + } + + /* Get the remote server */ + host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + if (!host) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + + /* Get port */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); + if (tmp) + SILC_GET32_MSB(port, tmp); + + /* Create the connection. It is done with timeout and is async. */ + silc_server_create_connection(server, host, port); + + /* Send reply to the sender */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT, + SILC_STATUS_OK); + + out: + silc_server_command_free(cmd); +} + +/* Server side command of CLOSE. Closes connection to a specified server. */ + +SILC_SERVER_CMD_FUNC(close) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; + SilcServerEntry server_entry; + SilcSocketConnection sock; + unsigned char *tmp; + SilcUInt32 tmp_len; + unsigned char *name; + SilcUInt32 port = SILC_PORT; + + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2); + + if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) + goto out; + + /* Check whether client has the permissions. */ + if (client->mode == SILC_UMODE_NONE) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE, + SILC_STATUS_ERR_NO_SERVER_PRIV); + goto out; + } + + /* Get the remote server */ + name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + if (!name) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + + /* Get port */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); + if (tmp) + SILC_GET32_MSB(port, tmp); + + server_entry = silc_idlist_find_server_by_conn(server->local_list, + name, port, FALSE, NULL); + if (!server_entry) + server_entry = silc_idlist_find_server_by_conn(server->global_list, + name, port, FALSE, NULL); + if (!server_entry) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE, + SILC_STATUS_ERR_NO_SERVER_ID); + goto out; + } + + /* Send reply to the sender */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE, + SILC_STATUS_OK); + + /* Close the connection to the server */ + sock = (SilcSocketConnection)server_entry->connection; + + /* If we shutdown primary router connection manually then don't trigger + any reconnect or backup router connections, by setting the router + to NULL here. */ + if (server->router == server_entry) { + server->id_entry->router = NULL; + server->router = NULL; + server->standalone = TRUE; + } + silc_server_free_sock_user_data(server, sock, NULL); + silc_server_close_connection(server, sock); + + out: + silc_server_command_free(cmd); +} + +/* Server side command of SHUTDOWN. Shutdowns the server and closes all + active connections. */ + +SILC_SERVER_CMD_FUNC(shutdown) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; + + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0); + + if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) + goto out; + + /* Check whether client has the permission. */ + if (client->mode == SILC_UMODE_NONE) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN, + SILC_STATUS_ERR_NO_SERVER_PRIV); + goto out; + } + + /* Send reply to the sender */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN, + SILC_STATUS_OK); + + /* Then, gracefully, or not, bring the server down. */ + silc_server_stop(server); + exit(0); + + out: + silc_server_command_free(cmd); +} diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 95fbcdd2..0b59e75f 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -130,24 +130,22 @@ SILC_SERVER_CMD_FUNC(invite); SILC_SERVER_CMD_FUNC(quit); SILC_SERVER_CMD_FUNC(kill); SILC_SERVER_CMD_FUNC(info); -SILC_SERVER_CMD_FUNC(connect); SILC_SERVER_CMD_FUNC(ping); SILC_SERVER_CMD_FUNC(oper); -SILC_SERVER_CMD_FUNC(pass); -SILC_SERVER_CMD_FUNC(admin); SILC_SERVER_CMD_FUNC(join); SILC_SERVER_CMD_FUNC(motd); SILC_SERVER_CMD_FUNC(umode); SILC_SERVER_CMD_FUNC(cmode); SILC_SERVER_CMD_FUNC(cumode); SILC_SERVER_CMD_FUNC(kick); -SILC_SERVER_CMD_FUNC(ignore); SILC_SERVER_CMD_FUNC(ban); -SILC_SERVER_CMD_FUNC(close); -SILC_SERVER_CMD_FUNC(shutdown); SILC_SERVER_CMD_FUNC(silcoper); SILC_SERVER_CMD_FUNC(leave); SILC_SERVER_CMD_FUNC(users); SILC_SERVER_CMD_FUNC(getkey); +SILC_SERVER_CMD_FUNC(connect); +SILC_SERVER_CMD_FUNC(close); +SILC_SERVER_CMD_FUNC(shutdown); + #endif diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index a04e1167..ab8f7d53 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -494,7 +494,7 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id, SilcClientEntry silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id, - SilcClientID *new_id) + SilcClientID *new_id, const char *nickname) { SilcIDCacheEntry id_cache = NULL; SilcClientEntry client; @@ -518,12 +518,17 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id, /* Remove the old entry and add a new one */ - silc_idcache_del_by_context(id_list->clients, client); + if (!silc_idcache_del_by_context(id_list->clients, client)) + return NULL; silc_free(client->id); + silc_free(client->nickname); client->id = new_id; + client->nickname = nickname ? strdup(nickname) : NULL; - silc_idcache_add(id_list->clients, NULL, client->id, client, 0, NULL); + if (!silc_idcache_add(id_list->clients, client->nickname, client->id, + client, 0, NULL)) + return NULL; SILC_LOG_DEBUG(("Replaced")); diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index 74139ceb..30fbd3a1 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -597,7 +597,7 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id, bool registered, SilcIDCacheEntry *ret_entry); SilcClientEntry silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id, - SilcClientID *new_id); + SilcClientID *new_id, const char *nickname); void silc_idlist_client_destructor(SilcIDCache cache, SilcIDCacheEntry entry); SilcChannelEntry diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index ab51f0e8..f0c3616d 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -426,6 +426,8 @@ void silc_server_notify(SilcServer server, * Distribute the notify to local clients on the channel */ unsigned char *id, *id2; + char *nickname; + SilcUInt32 nickname_len; SILC_LOG_DEBUG(("NICK CHANGE notify")); @@ -450,26 +452,24 @@ void silc_server_notify(SilcServer server, SILC_LOG_DEBUG(("New Client ID id(%s)", silc_id_render(client_id2, SILC_ID_CLIENT))); + /* From protocol version 1.1 we also get the new nickname */ + nickname = silc_argument_get_arg_type(args, 3, &nickname_len);; + /* Replace the Client ID */ client = silc_idlist_replace_client_id(server->global_list, client_id, - client_id2); + client_id2, nickname); if (!client) client = silc_idlist_replace_client_id(server->local_list, client_id, - client_id2); + client_id2, nickname); if (client) { - /* The nickname is not valid anymore, set it NULL. This causes that - the nickname will be queried if someone wants to know it. */ - if (client->nickname) - silc_free(client->nickname); - client->nickname = NULL; - /* Send the NICK_CHANGE notify type to local clients on the channels this client is joined to. */ - silc_server_send_notify_on_channels(server, NULL, client, - SILC_NOTIFY_TYPE_NICK_CHANGE, 2, - id, tmp_len, - id2, tmp_len); + silc_server_send_notify_on_channels(server, NULL, client, + SILC_NOTIFY_TYPE_NICK_CHANGE, 3, + id, tmp_len, id2, tmp_len, + nickname, nickname ? + nickname_len : 0); } silc_free(client_id); @@ -1126,8 +1126,7 @@ void silc_server_notify(SilcServer server, if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) goto out; - /* Get kicker. In protocol version 1.0 this is not mandatory argument - so we check it only if it is provided. */ + /* From protocol version 1.1 we get the kicker's ID as well. */ tmp = silc_argument_get_arg_type(args, 3, &tmp_len); if (tmp) { client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); @@ -1171,8 +1170,8 @@ void silc_server_notify(SilcServer server, /* * Distribute the notify to local clients on channels */ - unsigned char *id; - SilcUInt32 id_len; + unsigned char *id, *comment; + SilcUInt32 id_len, comment_len; SILC_LOG_DEBUG(("KILLED notify")); @@ -1207,16 +1206,42 @@ void silc_server_notify(SilcServer server, } /* Get comment */ - tmp = silc_argument_get_arg_type(args, 2, &tmp_len); - if (tmp_len > 128) - tmp = NULL; + comment = silc_argument_get_arg_type(args, 2, &comment_len); + if (comment_len > 128) + comment_len = 127; + + /* From protocol version 1.1 we get the killer's ID as well. */ + tmp = silc_argument_get_arg_type(args, 3, &tmp_len); + if (tmp) { + client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (!client_id) + goto out; + + /* If the the client is not in local list we check global list */ + client2 = silc_idlist_find_client_by_id(server->global_list, + client_id, TRUE, NULL); + if (!client2) { + client2 = silc_idlist_find_client_by_id(server->local_list, + client_id, TRUE, NULL); + if (!client2) { + silc_free(client_id); + goto out; + } + } + silc_free(client_id); + + /* Killer must be router operator */ + if (!(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) { + SILC_LOG_DEBUG(("Killing is not allowed")); + goto out; + } + } /* Send the notify to local clients on the channels except to the client who is killed. */ silc_server_send_notify_on_channels(server, client, client, - SILC_NOTIFY_TYPE_KILLED, - tmp ? 2 : 1, - id, id_len, + SILC_NOTIFY_TYPE_KILLED, 3, + id, id_len, comment, comment_len, tmp, tmp_len); /* Remove the client from all channels */ @@ -1577,6 +1602,7 @@ void silc_server_channel_message(SilcServer server, SilcChannelID *id = NULL; void *sender_id = NULL; SilcClientEntry sender_entry = NULL; + SilcChannelClientEntry chl; bool local = TRUE; SILC_LOG_DEBUG(("Processing channel message")); @@ -1615,11 +1641,24 @@ void silc_server_channel_message(SilcServer server, sender_id, TRUE, NULL); } if (!sender_entry || !silc_server_client_on_channel(sender_entry, - channel, NULL)) { + channel, &chl)) { SILC_LOG_DEBUG(("Client not on channel")); goto out; } + /* If channel is moderated check that client is allowed to send + messages. */ + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chl->mode) { + SILC_LOG_DEBUG(("Channel is silenced from normal users")); + goto out; + } + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && + chl->mode & SILC_CHANNEL_UMODE_CHANOP && + !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) { + SILC_LOG_DEBUG(("Channel is silenced from operators")); + goto out; + } + /* If the packet is coming from router, but the client entry is local entry to us then some router is rerouting this to us and it is not allowed. When the client is local to us it means that we've routed diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 05b3cd8c..424a2733 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1093,7 +1093,8 @@ void silc_server_send_notify_nick_change(SilcServer server, SilcSocketConnection sock, bool broadcast, SilcClientID *old_id, - SilcClientID *new_id) + SilcClientID *new_id, + const char *nickname) { SilcBuffer idp1, idp2; @@ -1102,7 +1103,8 @@ void silc_server_send_notify_nick_change(SilcServer server, silc_server_send_notify(server, sock, broadcast, SILC_NOTIFY_TYPE_NICK_CHANGE, - 2, idp1->data, idp1->len, idp2->data, idp2->len); + 3, idp1->data, idp1->len, idp2->data, idp2->len, + nickname, nickname ? strlen(nickname) : 0); silc_buffer_free(idp1); silc_buffer_free(idp2); } @@ -1284,16 +1286,21 @@ void silc_server_send_notify_killed(SilcServer server, SilcSocketConnection sock, bool broadcast, SilcClientID *client_id, - char *comment) + char *comment, + SilcClientID *killer) { - SilcBuffer idp; + SilcBuffer idp1; + SilcBuffer idp2; - idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT); + idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT); + idp2 = silc_id_payload_encode((void *)killer, SILC_ID_CLIENT); silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id, SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED, - comment ? 2 : 1, idp->data, idp->len, - comment, comment ? strlen(comment) : 0); - silc_buffer_free(idp); + 3, idp1->data, idp1->len, + comment, comment ? strlen(comment) : 0, + idp2->data, idp2->len); + silc_buffer_free(idp1); + silc_buffer_free(idp2); } /* Sends UMODE_CHANGE notify type. This tells that `client_id' client's diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index 3cd431f9..b2cbc8aa 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -123,7 +123,8 @@ void silc_server_send_notify_nick_change(SilcServer server, SilcSocketConnection sock, bool broadcast, SilcClientID *old_id, - SilcClientID *new_id); + SilcClientID *new_id, + const char *nickname); void silc_server_send_notify_join(SilcServer server, SilcSocketConnection sock, bool broadcast, @@ -171,7 +172,8 @@ void silc_server_send_notify_killed(SilcServer server, SilcSocketConnection sock, bool broadcast, SilcClientID *client_id, - char *comment); + char *comment, + SilcClientID *killer); void silc_server_send_notify_umode(SilcServer server, SilcSocketConnection sock, bool broadcast, diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index 65fafeea..eb7b3013 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -325,60 +325,36 @@ int silc_server_protocol_ke_set_keys(SilcServer server, SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version, SilcUInt32 len, void *context) { - SilcSKEStatus status = SILC_SKE_STATUS_OK; - char *cp; - int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0; + SilcUInt32 l_protocol_version = 0, r_protocol_version = 0; SILC_LOG_INFO(("%s (%s) is version %s", ske->sock->hostname, ske->sock->ip, version)); - /* Check for initial version string. Allowed "SILC-x.x-". More - specific protocol version is checked later in session. */ - if (!strstr(version, "SILC-")) - status = SILC_SKE_STATUS_BAD_VERSION; - - /* Check software version */ - - cp = version + 9; - if (!cp) - status = SILC_SKE_STATUS_BAD_VERSION; - - maj = atoi(cp); - cp = strchr(cp, '.'); - if (cp) { - min = atoi(cp + 1); - cp++; - } - if (cp) { - cp = strchr(cp, '.'); - if (cp) - build = atoi(cp + 1); + if (!silc_parse_version_string(version, &r_protocol_version, NULL, NULL, + NULL, NULL)) { + SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", + ske->sock->hostname, ske->sock->ip, version)); + return SILC_SKE_STATUS_BAD_VERSION; } - cp = silc_version_string + 9; - if (!cp) - status = SILC_SKE_STATUS_BAD_VERSION; - - maj2 = atoi(cp); - cp = strchr(cp, '.'); - if (cp) { - min2 = atoi(cp + 1); - cp++; - } - if (cp) { - cp = strchr(cp, '.'); - if (cp) - build2 = atoi(cp + 1); + if (!silc_parse_version_string(silc_version_string, + &l_protocol_version, NULL, NULL, + NULL, NULL)) { + SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", + ske->sock->hostname, ske->sock->ip, version)); + return SILC_SKE_STATUS_BAD_VERSION; } - if (maj != maj2) - status = SILC_SKE_STATUS_BAD_VERSION; - - if (status == SILC_SKE_STATUS_BAD_VERSION) + /* If remote is too new, don't connect */ + if (l_protocol_version < r_protocol_version) { SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", ske->sock->hostname, ske->sock->ip, version)); + return SILC_SKE_STATUS_BAD_VERSION; + } + + ske->sock->version = r_protocol_version; - return status; + return SILC_SKE_STATUS_OK; } /* Callback that is called by the SKE to indicate that it is safe to diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 147346de..01870b95 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -1056,6 +1056,28 @@ bool silc_server_check_cmode_rights(SilcServer server, } } + if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) { + if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) + if (is_op && !is_fo) + return FALSE; + } else { + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) { + if (is_op && !is_fo) + return FALSE; + } + } + + if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) { + if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) + if (is_op && !is_fo) + return FALSE; + } else { + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) { + if (is_op && !is_fo) + return FALSE; + } + } + return TRUE; } diff --git a/doc/draft-riikonen-silc-commands-03.nroff b/doc/draft-riikonen-silc-commands-03.nroff index 20c7d47f..d0dcd698 100644 --- a/doc/draft-riikonen-silc-commands-03.nroff +++ b/doc/draft-riikonen-silc-commands-03.nroff @@ -224,7 +224,7 @@ List of all defined commands in SILC follows. 1 SILC_COMMAND_WHOIS - Max Arguments: 3328 + Max Arguments: 256 Arguments: (1) [[@]] (2) [] (3) [] (n) [...] @@ -359,7 +359,7 @@ List of all defined commands in SILC follows. 3 SILC_COMMAND_IDENTIFY - Max Arguments: 3328 + Max Arguments: 256 Arguments: (1) [[@]] (2) [] (3) [] (4) [] (5) [] (n) [...] @@ -708,34 +708,7 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_NO_SERVER_ID - 11 SILC_COMMAND_CONNECT - - Max Arguments: 2 - Arguments: (1) (2) [] - - This command is used by operators to force a server to try to - establish a new connection to remote server or router. The - Operator MUST specify the server/router to be connected by - setting argument. The port is 32 bit MSB value. - - Reply messages to the command: - - Max Arguments: 1 - Arguments: (1) - - This command replies only with Status Payload. - - - - Status messages: - - SILC_STATUS_OK - SILC_STATUS_ERR_WILDCARDS - SILC_STATUS_ERR_NOT_REGISTERED - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS - SILC_STATUS_ERR_TOO_MANY_PARAMS - SILC_STATUS_ERR_NO_SERVER_PRIV - SILC_STATUS_ERR_NO_ROUTER_PRIV + 11 12 SILC_COMMAND_PING @@ -954,14 +927,14 @@ List of all defined commands in SILC follows. The following client modes are defined: - 0x0000 SILC_UMODE_NONE + 0x00000000 SILC_UMODE_NONE No specific mode for client. This is the initial setting when new client is created. The client is normal client now. - 0x0001 SILC_UMODE_SERVER_OPERATOR + 0x00000001 SILC_UMODE_SERVER_OPERATOR Marks the user as server operator. Client MUST NOT set this mode itself. Server sets this mode to the @@ -970,7 +943,7 @@ List of all defined commands in SILC follows. MAY unset the mode itself. - 0x0002 SILC_UMODE_ROUTER_OPERATOR + 0x00000002 SILC_UMODE_ROUTER_OPERATOR Marks the user as router (SILC) operator. Client MUST NOT this mode itself. Router sets this mode to @@ -979,7 +952,7 @@ List of all defined commands in SILC follows. MAY unset the mode itself. - 0x0004 SILC_UMODE_GONE + 0x00000004 SILC_UMODE_GONE Marks that the user is not currently present in the SILC Network. Client MAY set and unset this mode. @@ -1028,14 +1001,14 @@ List of all defined commands in SILC follows. The following channel modes are defined: - 0x0000 SILC_CMODE_NONE + 0x00000000 SILC_CMODE_NONE No specific mode on channel. This is the default when channel is created. This means that channel is just plain normal channel. - 0x0001 SILC_CMODE_PRIVATE + 0x00000001 SILC_CMODE_PRIVATE Channel is private channel. Private channels are shown in the channel list listed with SILC_COMMAND_LIST command @@ -1049,7 +1022,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0002 SILC_CMODE_SECRET + 0x00000002 SILC_CMODE_SECRET Channel is secret channel. Secret channels are not shown in the list listed with SILC_COMMAND_LIST command. Secret @@ -1061,7 +1034,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0004 SILC_CMODE_PRIVKEY + 0x00000004 SILC_CMODE_PRIVKEY Channel uses private channel key to protect the traffic on the channel. When this mode is set the client will be @@ -1093,7 +1066,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0008 SILC_CMODE_INVITE + 0x00000008 SILC_CMODE_INVITE Channel is invite only channel. Client may join to this channel only if it is invited to the channel. Channel @@ -1103,7 +1076,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0010 SILC_CMODE_TOPIC + 0x00000010 SILC_CMODE_TOPIC The topic of the channel may only be set by client that is channel founder or channel operator. Normal clients @@ -1115,7 +1088,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0020 SILC_CMODE_ULIMIT + 0x00000020 SILC_CMODE_ULIMIT User limit has been set to the channel. New clients may not join to the channel when the limit set is @@ -1127,7 +1100,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0040 SILC_CMODE_PASSPHRASE + 0x00000040 SILC_CMODE_PASSPHRASE Passphrase has been set to the channel. Client may join to the channel only if it is able to provide the @@ -1141,7 +1114,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0080 SILC_CMODE_CIPHER + 0x00000080 SILC_CMODE_CIPHER Sets specific cipher to be used to protect channel traffic. The argument is the requested cipher. @@ -1154,7 +1127,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0100 SILC_CMODE_HMAC + 0x00000100 SILC_CMODE_HMAC Sets specific hmac to be used to compute the MACs of the channel message. The argument is the requested hmac. @@ -1164,7 +1137,7 @@ List of all defined commands in SILC follows. to set/unset this mode. - 0x0200 SILC_CMODE_FOUNDER_AUTH + 0x00000200 SILC_CMODE_FOUNDER_AUTH Channel founder may set this mode to be able to regain channel founder rights even if the client leaves the @@ -1192,6 +1165,27 @@ List of all defined commands in SILC follows. Typical implementation would use [+|-]f on user interface to set/unset this mode. + + 0x00000400 SILC_CMODE_SILENCE_USERS + + Channel founder may set this mode to silence normal users + on the channel. Users with operator privileges are not + affected by this mode. Messages sent by normal users + are dropped by servers when this mode is set. This mode + can be used to moderate the channel. Only channel founder + may set/unset this mode. + + + 0x00000800 SILC_CMODE_SILENCE_OPERS + + Channel founder may set this mode to silence operators + on the channel. When used with SILC_CMODE_SILENCE_USERS + mode this can be used to set the channel in state where only + the founder of the channel may send messages to the channel. + Messages sent by operators are dropped by servers when this + mode is set. Only channel founder may set/unset this mode. + + To make the mode system work, client MUST keep the channel mode mask locally so that the mode setting and unsetting would work without problems. The client receives the initial channel mode @@ -1221,6 +1215,7 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_BAD_CHANNEL_ID SILC_STATUS_ERR_NO_CHANNEL_ID SILC_STATUS_ERR_NO_CHANNEL_PRIV + SILC_STATUS_ERR_NO_CHANNEL_FOPRIV SILC_STATUS_ERR_UNKNOWN_MODE SILC_STATUS_ERR_NO_SUCH_CLIENT_ID SILC_STATUS_ERR_AUTH_FAILED @@ -1246,14 +1241,14 @@ List of all defined commands in SILC follows. The following channel modes are defined: - 0x0000 SILC_CUMODE_NONE + 0x00000000 SILC_CUMODE_NONE No specific mode. This is the normal situation for client. Also, this is the mode set when removing all modes from the target client. - 0x0001 SILC_CUMODE_FOUNDER + 0x00000001 SILC_CUMODE_FOUNDER The client is channel founder of the channel. Usually this mode is set only by the server when the channel was created. @@ -1266,7 +1261,7 @@ List of all defined commands in SILC follows. mode was set. The client MAY remove this mode at any time. - 0x0002 SILC_CUMODE_OPERATOR + 0x00000002 SILC_CUMODE_OPERATOR Sets channel operator privileges on the channel for a client on the channel. Channel founder and channel operator @@ -1293,6 +1288,7 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_BAD_CHANNEL_ID SILC_STATUS_ERR_NO_CHANNEL_ID SILC_STATUS_ERR_NO_CHANNEL_PRIV + SILC_STATUS_ERR_NO_CHANNEL_FOPRIV SILC_STATUS_ERR_UNKNOWN_MODE SILC_STATUS_ERR_NO_SUCH_CLIENT_ID SILC_STATUS_ERR_AUTH_FAILED @@ -1381,53 +1377,10 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_NO_CHANNEL_PRIV - 21 SILC_COMMAND_CLOSE - - Max Arguments: 2 - Arguments: (1) (2) [] - - This command is used only by operator to close connection to a - remote site. - - Reply messages to the command: - - Max Arguments: 1 - Arguments: (1) + 21 - This command replies only with Status Payload. - Status messages: - - SILC_STATUS_OK - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS - SILC_STATUS_ERR_TOO_MANY_PARAMS - SILC_STATUS_ERR_NOT_REGISTERED - SILC_STATUS_ERR_NO_SUCH_SERVER - SILC_STATUS_ERR_NO_SERVER_PRIV - SILC_STATUS_ERR_NO_SUCH_SERVER_ID - - - 22 SILC_COMMAND_SHUTDOWN - - Max Arguments: 0 - Arguments: None - - This command is used only by operator to shutdown the server. - All connections to the server will be closed and the server is - shutdown. - - Reply messages to the command: - - Max Arguments: 1 - Arguments: (1) - - This command replies only with Status Payload. - - Status messages: - - SILC_STATUS_OK - SILC_STATUS_ERR_NOT_REGISTERED - SILC_STATUS_ERR_NO_SERVER_PRIV + 22 23 SILC_COMMAND_SILCOPER @@ -1493,10 +1446,10 @@ List of all defined commands in SILC follows. Reply messages to the command: - Max Arguments: 1 - Arguments: (1) + Max Arguments: 2 + Arguments: (1) (2) - This command replies only with Status Payload. + The is the ID of left channel. Status messages: diff --git a/doc/draft-riikonen-silc-pp-05.nroff b/doc/draft-riikonen-silc-pp-05.nroff index a8ed3e67..31b557d7 100644 --- a/doc/draft-riikonen-silc-pp-05.nroff +++ b/doc/draft-riikonen-silc-pp-05.nroff @@ -1295,12 +1295,13 @@ Also, all ID's sent in arguments are sent inside ID Payload. receiving the packet distributes this type to the local clients on the channel and broadcast it to the network. - Max Arguments: 2 + Max Arguments: 3 Arguments: (1) (2) + (3) The is the old ID of the client which changed the nickname. The is the new ID generated by - the change of the nickname. + the change of the nickname. The is the new nickname. 7 SILC_NOTIFY_TYPE_CMODE_CHANGE @@ -1415,12 +1416,13 @@ Also, all ID's sent in arguments are sent inside ID Payload. or server receiving the packet distributes this type to the local clients on the channel and broadcast it to the network. - Max Arguments: 2 - Arguments: (1) (2) [] + Max Arguments: 3 + Arguments: (1) (2) [] + (3) The is the client which was killed from the network. The killer may have set the to indicate the reason for - the killing. + the killing. The is the killer. 14 SILC_NOTIFY_TYPE_UMODE_CHANGE @@ -1604,11 +1606,26 @@ o Message Flags (2 bytes) - Includes the Message Flags of of the signing process and any associated payloads of this flag. - 0x0040 - 0x0200 RESERVED + 0x0040 SILC_MESSAGE_FLAG_REPLY + + This is a generic reply flag to send a reply to + previously received request. A separate document + should define any payloads associated to this flag. + + 0x0080 SILC_MESSAGE_FLAG_DATA + + This is a generic data flag, indicating that the + message includes some data which can be interpreted + in a specific way. Using this flag any kind of data + can be delivered inside message payload. A separate + document should define how this flag is interpreted + and define any associated payloads. + + 0x0100 - 0x0800 RESERVED Reserved for future flags - 0x0400 - 0x8000 PRIVATE RANGE + 0x1000 - 0x8000 PRIVATE RANGE Private range for free use. diff --git a/doc/draft-riikonen-silc-spec-05.nroff b/doc/draft-riikonen-silc-spec-05.nroff index e5181fdd..ae9a85bb 100644 --- a/doc/draft-riikonen-silc-spec-05.nroff +++ b/doc/draft-riikonen-silc-spec-05.nroff @@ -1422,7 +1422,7 @@ software version = [.[.]] Protocol version MAY provide both major and minor version. Currently implementations MUST set the protocol version and accept the protocol -version as SILC-1.0-. If new protocol version causes +version as SILC-1.1-. If new protocol version causes in compatibilities with older version the the versio number MUST be incremented. The is incremented if new protocol version is fully incompatible. @@ -1434,9 +1434,9 @@ software version MAY be freely set and accepted. Thus, the version strings could be, for example: .in 6 -SILC-1.0-1.2 SILC-1.1-2.0.2 -SILC-1.0-1.0.VendorXYZ +SILC-1.0-1.2 +SILC-1.1-1.0.VendorXYZ .in 3 diff --git a/doc/example_silcd.conf.in b/doc/example_silcd.conf.in index bf7db76b..53414eb6 100644 --- a/doc/example_silcd.conf.in +++ b/doc/example_silcd.conf.in @@ -71,7 +71,7 @@ General { # number of the software. The string can be a regex string to match # more widely. Usually the vendor version checking is not necessary # and can be omitted. These can be overridden with ConnectionParams. - #version_protocol = "1.0"; + #version_protocol = "1.1"; #version_software = "1.3"; #version_software_vendor = "SomeVendor"; @@ -284,7 +284,7 @@ ConnectionParams { # number of the software. The string can be a regex string to match # more widely. Usually the vendor version checking is not necessary # and can be omitted. - #version_protocol = "1.0"; + #version_protocol = "1.1"; #version_software = "1.3"; #version_software_vendor = "SomeVendor"; diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index ff2f6d02..8d781039 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -52,9 +52,24 @@ void silc_client_send_channel_message(SilcClient client, unsigned char *id_string; SilcUInt32 iv_len; int block_len; + SilcChannelUser chu; SILC_LOG_DEBUG(("Sending packet to channel")); + chu = silc_client_on_channel(channel, conn->local_entry); + if (!chu) { + SILC_LOG_ERROR(("Cannot send message to channel we are not joined")); + return; + } + + /* Check if it is allowed to send messages to this channel by us. */ + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode) + return; + if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && + chu->mode & SILC_CHANNEL_UMODE_CHANOP && + !(chu->mode & SILC_CHANNEL_UMODE_CHANFO)) + return; + /* Take the key to be used */ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) { if (key) { @@ -173,6 +188,7 @@ static void silc_client_channel_message_cb(SilcClient client, if (clients_count == 1) { SilcChannelEntry channel; unsigned char *message; + SilcUInt32 message_len; channel = silc_client_get_channel_by_id(client, conn, res->channel_id); if (!channel) @@ -188,13 +204,13 @@ static void silc_client_channel_message_cb(SilcClient client, silc_hash_table_add(clients[0]->channels, channel, chu); } - message = silc_channel_message_get_data(res->payload, NULL); + message = silc_channel_message_get_data(res->payload, &message_len); /* Pass the message to application */ client->internal->ops->channel_message( client, conn, clients[0], channel, silc_channel_message_get_flags(res->payload), - message); + message, message_len); } out: @@ -219,6 +235,7 @@ void silc_client_channel_message(SilcClient client, SilcClientEntry client_entry; SilcClientID *client_id = NULL; unsigned char *message; + SilcUInt32 message_len; SILC_LOG_DEBUG(("Start")); @@ -301,13 +318,13 @@ void silc_client_channel_message(SilcClient client, goto out; } - message = silc_channel_message_get_data(payload, NULL); + message = silc_channel_message_get_data(payload, &message_len); /* Pass the message to application */ client->internal->ops->channel_message( client, conn, client_entry, channel, silc_channel_message_get_flags(payload), - message); + message, message_len); out: silc_free(id); diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 5dde20b5..797b464e 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -479,41 +479,71 @@ void silc_client_notify_by_server(SilcClient client, if (!client_id) goto out; - /* Find Client entry and if not found resolve it */ - client_entry2 = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry2) { - /* Resolve the entry information */ - silc_client_notify_by_server_resolve(client, conn, packet, - SILC_ID_CLIENT, client_id); - - /* Add the new entry even though we resolved it. This is because we - want to replace the old entry with the new entry here right now. */ - client_entry2 = - silc_client_add_client(client, conn, NULL, NULL, NULL, - silc_id_dup(client_id, SILC_ID_CLIENT), - client_entry->mode); + /* From protocol version 1.1 we get the new nickname in notify as well, + so we don't have to resolve it. Do it the hard way if server doesn't + send it to us. */ + tmp = silc_argument_get_arg_type(args, 3, NULL); + if (tmp) { + /* Protocol version 1.1 */ + + /* Create new client entry, and save all old information with the + new nickname and client ID */ + client_entry2 = silc_client_add_client(client, conn, NULL, NULL, + client_entry->realname, + silc_id_dup(client_id, + SILC_ID_CLIENT), 0); + if (!client_entry2) + goto out; - /* Replace old ID entry with new one on all channels. */ - silc_client_replace_from_channels(client, conn, client_entry, - client_entry2); + if (client_entry->server) + client_entry2->server = strdup(client_entry->server); + if (client_entry->username) + client_entry2->username = strdup(client_entry->username); + if (client_entry->hostname) + client_entry2->hostname = strdup(client_entry->hostname); + silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL, + client_entry->mode); } else { + /* Protocol version 1.0 */ + + /* Find client entry and if not found resolve it */ + client_entry2 = silc_client_get_client_by_id(client, conn, client_id); + if (!client_entry2) { + /* Resolve the entry information */ + silc_client_notify_by_server_resolve(client, conn, packet, + SILC_ID_CLIENT, client_id); + + /* Add the new entry even though we resolved it. This is because we + want to replace the old entry with the new entry here right now. */ + client_entry2 = + silc_client_add_client(client, conn, NULL, NULL, NULL, + silc_id_dup(client_id, SILC_ID_CLIENT), + client_entry->mode); + + /* Replace old ID entry with new one on all channels. */ + silc_client_replace_from_channels(client, conn, client_entry, + client_entry2); + break; + } + if (client_entry2 != conn->local_entry) silc_client_nickname_format(client, conn, client_entry2); + } - /* Remove the old from cache */ - silc_idcache_del_by_context(conn->client_cache, client_entry); - - /* Replace old ID entry with new one on all channels. */ - silc_client_replace_from_channels(client, conn, client_entry, - client_entry2); + /* Remove the old from cache */ + silc_idcache_del_by_context(conn->client_cache, client_entry); + + /* Replace old ID entry with new one on all channels. */ + silc_client_replace_from_channels(client, conn, client_entry, + client_entry2); - /* Notify application */ - client->internal->ops->notify(client, conn, type, - client_entry, client_entry2); + /* Notify application */ + client->internal->ops->notify(client, conn, type, + client_entry, client_entry2); + + /* Free old client entry */ + silc_client_del_client_entry(client, conn, client_entry); - /* Free data */ - silc_client_del_client_entry(client, conn, client_entry); - } break; case SILC_NOTIFY_TYPE_CMODE_CHANGE: @@ -795,9 +825,10 @@ void silc_client_notify_by_server(SilcClient client, if (!channel) break; - /* Get the kicker */ + /* From protocol version 1.1 we get the kicker's client ID as well */ tmp = silc_argument_get_arg_type(args, 3, &tmp_len); if (tmp) { + silc_free(client_id); client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); if (!client_id) goto out; @@ -840,36 +871,60 @@ void silc_client_notify_by_server(SilcClient client, break; case SILC_NOTIFY_TYPE_KILLED: - /* - * A client (maybe me) was killed from the network. - */ + { + /* + * A client (maybe me) was killed from the network. + */ + char *comment; + SilcUInt32 comment_len; - SILC_LOG_DEBUG(("Notify: KILLED")); + SILC_LOG_DEBUG(("Notify: KILLED")); - /* Get Client ID */ - tmp = silc_argument_get_arg_type(args, 1, &tmp_len); - if (!tmp) - goto out; - - client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); - if (!client_id) - goto out; + /* Get Client ID */ + tmp = silc_argument_get_arg_type(args, 1, &tmp_len); + if (!tmp) + goto out; - /* Find Client entry */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - goto out; + client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (!client_id) + goto out; - /* Get comment */ - tmp = silc_argument_get_arg_type(args, 2, &tmp_len); + /* Find Client entry */ + client_entry = silc_client_get_client_by_id(client, conn, client_id); + if (!client_entry) + goto out; - /* Notify application. */ - client->internal->ops->notify(client, conn, type, client_entry, tmp); + /* Get comment */ + comment = silc_argument_get_arg_type(args, 2, &comment_len); + + /* From protocol version 1.1 we get killer's client ID as well */ + tmp = silc_argument_get_arg_type(args, 3, &tmp_len); + if (tmp) { + silc_free(client_id); + client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (!client_id) + goto out; + + /* Find killer's client entry and if not found resolve it */ + client_entry2 = silc_client_get_client_by_id(client, conn, client_id); + if (!client_entry2) { + silc_client_notify_by_server_resolve(client, conn, packet, + SILC_ID_CLIENT, client_id); + goto out; + } else { + if (client_entry2 != conn->local_entry) + silc_client_nickname_format(client, conn, client_entry2); + } + } - if (client_entry != conn->local_entry) - /* Remove the client from all channels and free it */ - silc_client_del_client(client, conn, client_entry); + /* Notify application. */ + client->internal->ops->notify(client, conn, type, client_entry, + comment, client_entry2); + if (client_entry != conn->local_entry) + /* Remove the client from all channels and free it */ + silc_client_del_client(client, conn, client_entry); + } break; case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: diff --git a/lib/silcclient/client_ops_example.c b/lib/silcclient/client_ops_example.c index bb17c1a4..7ecb981b 100644 --- a/lib/silcclient/client_ops_example.c +++ b/lib/silcclient/client_ops_example.c @@ -29,7 +29,8 @@ silc_say(SilcClient client, SilcClientConnection conn, static void silc_channel_message(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, - SilcMessageFlags flags, char *msg) + SilcMessageFlags flags, const unsigned char *message, + SilcUInt32 message_len); { } @@ -40,7 +41,9 @@ silc_channel_message(SilcClient client, SilcClientConnection conn, static void silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessageFlags flags, char *msg) + SilcClientEntry sender, SilcMessageFlags flags, + const unsigned char *message, + SilcUInt32 message_len); { } diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index c229b450..a6e09917 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -148,6 +148,8 @@ void silc_client_private_message(SilcClient client, SilcClientID *remote_id = NULL; SilcClientEntry remote_client; SilcMessageFlags flags; + unsigned char *message; + SilcUInt32 message_len; if (packet->src_id_type != SILC_ID_CLIENT) goto out; @@ -187,10 +189,9 @@ void silc_client_private_message(SilcClient client, flags = silc_private_message_get_flags(payload); /* Pass the private message to application */ - client->internal->ops->private_message( - client, conn, remote_client, flags, - silc_private_message_get_message(payload, - NULL)); + message = silc_private_message_get_message(payload, &message_len); + client->internal->ops->private_message(client, conn, remote_client, flags, + message, message_len); /* See if we are away (gone). If we are away we will reply to the sender with the set away message. */ diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index c0c058d0..7ffc279f 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -1252,6 +1252,18 @@ SILC_CLIENT_CMD_FUNC(cmode) else mode &= ~SILC_CHANNEL_MODE_TOPIC; break; + case 'm': + if (add) + mode |= SILC_CHANNEL_MODE_SILENCE_USERS; + else + mode &= ~SILC_CHANNEL_MODE_SILENCE_USERS; + break; + case 'M': + if (add) + mode |= SILC_CHANNEL_MODE_SILENCE_OPERS; + else + mode &= ~SILC_CHANNEL_MODE_SILENCE_OPERS; + break; case 'l': if (add) { int ll; @@ -1785,54 +1797,6 @@ SILC_CLIENT_CMD_FUNC(silcoper) silc_client_command_free(cmd); } -/* CONNECT command. Connects the server to another server. */ - -SILC_CLIENT_CMD_FUNC(connect) -{ - SilcClientCommandContext cmd = (SilcClientCommandContext)context; - SilcClientConnection conn = cmd->conn; - SilcBuffer buffer; - unsigned char port[4]; - SilcUInt32 tmp; - - if (!cmd->conn) { - SILC_NOT_CONNECTED(cmd->client, cmd->conn); - COMMAND_ERROR; - goto out; - } - - if (cmd->argc < 2) { - SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Usage: /CONNECT []"); - COMMAND_ERROR; - goto out; - } - - if (cmd->argc == 3) { - tmp = atoi(cmd->argv[2]); - SILC_PUT32_MSB(tmp, port); - } - - if (cmd->argc == 3) - buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 2, - 1, cmd->argv[1], - strlen(cmd->argv[1]), - 2, port, 4); - else - buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 1, - 1, cmd->argv[1], - strlen(cmd->argv[1])); - silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, - 0, NULL, NULL, buffer->data, buffer->len, TRUE); - silc_buffer_free(buffer); - - /* Notify application */ - COMMAND; - - out: - silc_client_command_free(cmd); -} - /* Command BAN. This is used to manage the ban list of the channel. */ SILC_CLIENT_CMD_FUNC(ban) @@ -1912,77 +1876,6 @@ SILC_CLIENT_CMD_FUNC(ban) silc_client_command_free(cmd); } -/* CLOSE command. Close server connection to the remote server */ - -SILC_CLIENT_CMD_FUNC(close) -{ - SilcClientCommandContext cmd = (SilcClientCommandContext)context; - SilcClientConnection conn = cmd->conn; - SilcBuffer buffer; - unsigned char port[4]; - SilcUInt32 tmp; - - if (!cmd->conn) { - SILC_NOT_CONNECTED(cmd->client, cmd->conn); - COMMAND_ERROR; - goto out; - } - - if (cmd->argc < 2) { - SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Usage: /CLOSE []"); - COMMAND_ERROR; - goto out; - } - - if (cmd->argc == 3) { - tmp = atoi(cmd->argv[2]); - SILC_PUT32_MSB(tmp, port); - } - - if (cmd->argc == 3) - buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 2, - 1, cmd->argv[1], - strlen(cmd->argv[1]), - 2, port, 4); - else - buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 1, - 1, cmd->argv[1], - strlen(cmd->argv[1])); - silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, - 0, NULL, NULL, buffer->data, buffer->len, TRUE); - silc_buffer_free(buffer); - - /* Notify application */ - COMMAND; - - out: - silc_client_command_free(cmd); -} - -/* SHUTDOWN command. Shutdowns the server. */ - -SILC_CLIENT_CMD_FUNC(shutdown) -{ - SilcClientCommandContext cmd = (SilcClientCommandContext)context; - - if (!cmd->conn) { - SILC_NOT_CONNECTED(cmd->client, cmd->conn); - COMMAND_ERROR; - goto out; - } - - /* Send the command */ - silc_client_command_send(cmd->client, cmd->conn, - SILC_COMMAND_SHUTDOWN, 0, 0); - - /* Notify application */ - COMMAND; - - out: - silc_client_command_free(cmd); -} - /* LEAVE command. Leaves a channel. Client removes itself from a channel. */ SILC_CLIENT_CMD_FUNC(leave) @@ -2282,6 +2175,129 @@ bool silc_client_command_unregister(SilcClient client, return FALSE; } +/* Private range commands, specific to this implementation (and compatible + with SILC Server). */ + +/* CONNECT command. Connects the server to another server. */ + +SILC_CLIENT_CMD_FUNC(connect) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer; + unsigned char port[4]; + SilcUInt32 tmp; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc < 2) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CONNECT []"); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc == 3) { + tmp = atoi(cmd->argv[2]); + SILC_PUT32_MSB(tmp, port); + } + + if (cmd->argc == 3) + buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2, + 1, cmd->argv[1], + strlen(cmd->argv[1]), + 2, port, 4); + else + buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 1, + 1, cmd->argv[1], + strlen(cmd->argv[1])); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, + 0, NULL, NULL, buffer->data, buffer->len, TRUE); + silc_buffer_free(buffer); + + /* Notify application */ + COMMAND; + + out: + silc_client_command_free(cmd); +} + + +/* CLOSE command. Close server connection to the remote server */ + +SILC_CLIENT_CMD_FUNC(close) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer; + unsigned char port[4]; + SilcUInt32 tmp; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc < 2) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CLOSE []"); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc == 3) { + tmp = atoi(cmd->argv[2]); + SILC_PUT32_MSB(tmp, port); + } + + if (cmd->argc == 3) + buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2, + 1, cmd->argv[1], + strlen(cmd->argv[1]), + 2, port, 4); + else + buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 1, + 1, cmd->argv[1], + strlen(cmd->argv[1])); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, + 0, NULL, NULL, buffer->data, buffer->len, TRUE); + silc_buffer_free(buffer); + + /* Notify application */ + COMMAND; + + out: + silc_client_command_free(cmd); +} + +/* SHUTDOWN command. Shutdowns the server. */ + +SILC_CLIENT_CMD_FUNC(shutdown) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); + COMMAND_ERROR; + goto out; + } + + /* Send the command */ + silc_client_command_send(cmd->client, cmd->conn, + SILC_COMMAND_PRIV_SHUTDOWN, 0, 0); + + /* Notify application */ + COMMAND; + + out: + silc_client_command_free(cmd); +} + /* Register all default commands provided by the client library for the application. */ @@ -2300,7 +2316,6 @@ void silc_client_commands_register(SilcClient client) SILC_CLIENT_CMD(quit, QUIT, "QUIT", 2); SILC_CLIENT_CMD(kill, KILL, "KILL", 3); SILC_CLIENT_CMD(info, INFO, "INFO", 2); - SILC_CLIENT_CMD(connect, CONNECT, "CONNECT", 3); SILC_CLIENT_CMD(ping, PING, "PING", 2); SILC_CLIENT_CMD(oper, OPER, "OPER", 3); SILC_CLIENT_CMD(join, JOIN, "JOIN", 9); @@ -2310,12 +2325,14 @@ void silc_client_commands_register(SilcClient client) SILC_CLIENT_CMD(cumode, CUMODE, "CUMODE", 5); SILC_CLIENT_CMD(kick, KICK, "KICK", 4); SILC_CLIENT_CMD(ban, BAN, "BAN", 3); - SILC_CLIENT_CMD(close, CLOSE, "CLOSE", 3); - SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN", 1); SILC_CLIENT_CMD(silcoper, SILCOPER, "SILCOPER", 3); SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", 2); SILC_CLIENT_CMD(users, USERS, "USERS", 2); SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", 2); + + SILC_CLIENT_CMD(connect, PRIV_CONNECT, "CONNECT", 3); + SILC_CLIENT_CMD(close, PRIV_CLOSE, "CLOSE", 3); + SILC_CLIENT_CMD(shutdown, PRIV_SHUTDOWN, "SHUTDOWN", 1); } /* Unregister all commands. */ @@ -2332,7 +2349,6 @@ void silc_client_commands_unregister(SilcClient client) SILC_CLIENT_CMDU(quit, QUIT, "QUIT"); SILC_CLIENT_CMDU(kill, KILL, "KILL"); SILC_CLIENT_CMDU(info, INFO, "INFO"); - SILC_CLIENT_CMDU(connect, CONNECT, "CONNECT"); SILC_CLIENT_CMDU(ping, PING, "PING"); SILC_CLIENT_CMDU(oper, OPER, "OPER"); SILC_CLIENT_CMDU(join, JOIN, "JOIN"); @@ -2342,10 +2358,12 @@ void silc_client_commands_unregister(SilcClient client) SILC_CLIENT_CMDU(cumode, CUMODE, "CUMODE"); SILC_CLIENT_CMDU(kick, KICK, "KICK"); SILC_CLIENT_CMDU(ban, BAN, "BAN"); - SILC_CLIENT_CMDU(close, CLOSE, "CLOSE"); - SILC_CLIENT_CMDU(shutdown, SHUTDOWN, "SHUTDOWN"); SILC_CLIENT_CMDU(silcoper, SILCOPER, "SILCOPER"); SILC_CLIENT_CMDU(leave, LEAVE, "LEAVE"); SILC_CLIENT_CMDU(users, USERS, "USERS"); SILC_CLIENT_CMDU(getkey, GETKEY, "GETKEY"); + + SILC_CLIENT_CMDU(connect, PRIV_CONNECT, "CONNECT"); + SILC_CLIENT_CMDU(close, PRIV_CLOSE, "CLOSE"); + SILC_CLIENT_CMDU(shutdown, PRIV_SHUTDOWN, "SHUTDOWN"); } diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 9246831c..289b1917 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -1356,26 +1356,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper) silc_client_command_reply_free(cmd); } -SILC_CLIENT_CMD_REPLY_FUNC(connect) -{ - SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; - SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; - - if (cmd->status != SILC_STATUS_OK) { - SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->status)); - COMMAND_REPLY_ERROR; - goto out; - } - - /* Notify application */ - COMMAND_REPLY((ARGS)); - - out: - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CONNECT); - silc_client_command_reply_free(cmd); -} - SILC_CLIENT_CMD_REPLY_FUNC(ban) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; @@ -1420,30 +1400,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban) silc_client_command_reply_free(cmd); } -SILC_CLIENT_CMD_REPLY_FUNC(close) -{ - SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; - SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; - - if (cmd->status != SILC_STATUS_OK) { - SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->status)); - COMMAND_REPLY_ERROR; - goto out; - } - - /* Notify application */ - COMMAND_REPLY((ARGS)); +/* Reply to LEAVE command. */ - out: - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE); - silc_client_command_reply_free(cmd); -} - -SILC_CLIENT_CMD_REPLY_FUNC(shutdown) +SILC_CLIENT_CMD_REPLY_FUNC(leave) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcChannelID *channel_id; + SilcChannelEntry channel = NULL; + unsigned char *tmp; + SilcUInt32 len; if (cmd->status != SILC_STATUS_OK) { SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, @@ -1452,30 +1418,26 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown) goto out; } - /* Notify application */ - COMMAND_REPLY((ARGS)); - - out: - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SHUTDOWN); - silc_client_command_reply_free(cmd); -} - -/* Reply to LEAVE command. */ + /* From protocol version 1.1 we get the channel ID of the left channel */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (tmp) { + channel_id = silc_id_payload_parse_id(tmp, len, NULL); + if (!channel_id) + goto out; -SILC_CLIENT_CMD_REPLY_FUNC(leave) -{ - SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; - SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + /* Get the channel entry */ + channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id); + if (!channel) { + silc_free(channel_id); + COMMAND_REPLY_ERROR; + goto out; + } - if (cmd->status != SILC_STATUS_OK) { - SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_client_command_status_message(cmd->status)); - COMMAND_REPLY_ERROR; - goto out; + silc_free(channel_id); } /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((ARGS, channel)); out: SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE); @@ -1955,3 +1917,68 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i) silc_free(server_id); silc_client_command_reply_free(cmd); } + + +/* Private range commands, specific to this implementation (and compatible + with SILC Server). */ + +SILC_CLIENT_CMD_REPLY_FUNC(connect) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + + if (cmd->status != SILC_STATUS_OK) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(cmd->status)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Notify application */ + COMMAND_REPLY((ARGS)); + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CONNECT); + silc_client_command_reply_free(cmd); +} + +SILC_CLIENT_CMD_REPLY_FUNC(close) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + + if (cmd->status != SILC_STATUS_OK) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(cmd->status)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Notify application */ + COMMAND_REPLY((ARGS)); + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CLOSE); + silc_client_command_reply_free(cmd); +} + +SILC_CLIENT_CMD_REPLY_FUNC(shutdown) +{ + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + + if (cmd->status != SILC_STATUS_OK) { + SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", silc_client_command_status_message(cmd->status)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Notify application */ + COMMAND_REPLY((ARGS)); + + out: + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_SHUTDOWN); + silc_client_command_reply_free(cmd); +} + diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index 4452df4e..5f9f4437 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -281,13 +281,16 @@ typedef struct { `msg' maybe NULL. */ void (*channel_message)(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, - SilcMessageFlags flags, char *msg); + SilcMessageFlags flags, + const unsigned char *message, + SilcUInt32 message_len); /* Private message to the client. The `sender' is the sender of the message. */ void (*private_message)(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessageFlags flags, - char *msg); + const unsigned char *message, + SilcUInt32 message_len); /* Notify message to the client. The notify arguments are sent in the same order as servers sends them. The arguments are same as received diff --git a/lib/silccore/silcchannel.h b/lib/silccore/silcchannel.h index 6d97e1a2..788ef384 100644 --- a/lib/silccore/silcchannel.h +++ b/lib/silccore/silcchannel.h @@ -111,8 +111,10 @@ typedef SilcUInt16 SilcMessageFlags; #define SILC_MESSAGE_FLAG_NOTICE 0x0008 #define SILC_MESSAGE_FLAG_REQUEST 0x0010 #define SILC_MESSAGE_FLAG_SIGNED 0x0020 -#define SILC_MESSAGE_FLAG_RESERVED 0x0040 /* to 0x0200 */ -#define SILC_MESSAGE_FLAG_PRIVATE 0x0400 /* to 0x8000 */ +#define SILC_MESSAGE_FLAG_REPLY 0x0040 +#define SILC_MESSAGE_FLAG_DATA 0x0080 +#define SILC_MESSAGE_FLAG_RESERVED 0x0100 /* to 0x0800 */ +#define SILC_MESSAGE_FLAG_PRIVATE 0x1000 /* to 0x8000 */ /***/ /* Prototypes */ diff --git a/lib/silccore/silccommand.h b/lib/silccore/silccommand.h index a34f3d68..4e84bd5b 100644 --- a/lib/silccore/silccommand.h +++ b/lib/silccore/silccommand.h @@ -134,7 +134,6 @@ typedef unsigned char SilcCommand; #define SILC_COMMAND_QUIT 8 #define SILC_COMMAND_KILL 9 #define SILC_COMMAND_INFO 10 -#define SILC_COMMAND_CONNECT 11 #define SILC_COMMAND_PING 12 #define SILC_COMMAND_OPER 13 #define SILC_COMMAND_JOIN 14 @@ -144,13 +143,16 @@ typedef unsigned char SilcCommand; #define SILC_COMMAND_CUMODE 18 #define SILC_COMMAND_KICK 19 #define SILC_COMMAND_BAN 20 -#define SILC_COMMAND_CLOSE 21 -#define SILC_COMMAND_SHUTDOWN 22 #define SILC_COMMAND_SILCOPER 23 #define SILC_COMMAND_LEAVE 24 #define SILC_COMMAND_USERS 25 #define SILC_COMMAND_GETKEY 26 +/* Private range start */ +#define SILC_COMMAND_PRIV_CONNECT 200 +#define SILC_COMMAND_PRIV_CLOSE 201 +#define SILC_COMMAND_PRIV_SHUTDOWN 202 + /* Reserved */ #define SILC_COMMAND_RESERVED 255 /***/ diff --git a/lib/silccore/silcmode.h b/lib/silccore/silcmode.h index 4e365bf7..6f47e7f8 100644 --- a/lib/silccore/silcmode.h +++ b/lib/silccore/silcmode.h @@ -50,6 +50,8 @@ #define SILC_CHANNEL_MODE_CIPHER 0x0080 /* sets cipher of the channel */ #define SILC_CHANNEL_MODE_HMAC 0x0100 /* sets hmac of the channel */ #define SILC_CHANNEL_MODE_FOUNDER_AUTH 0x0200 /* sets founder auth data */ +#define SILC_CHANNEL_MODE_SILENCE_USERS 0x0400 /* sets founder auth data */ +#define SILC_CHANNEL_MODE_SILENCE_OPERS 0x0800 /* sets founder auth data */ /***/ /****d* silccore/Modes/ChannelUserModes diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index 1473fc80..f0c0e7b6 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -769,6 +769,12 @@ char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac) if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) strncat(string, "f", 1); + if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) + strncat(string, "m", 1); + + if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) + strncat(string, "M", 1); + if (mode & SILC_CHANNEL_MODE_CIPHER) strncat(string, cipher, strlen(cipher)); diff --git a/prepare b/prepare index 71c75d63..f5cfff57 100755 --- a/prepare +++ b/prepare @@ -142,7 +142,7 @@ file=includes/version_internal.h echo "/* Automatically generated by ./prepare */" >$file echo "#define SILC_VERSION_STRING \"$version\"" >>$file echo "#define SILC_DIST_VERSION_STRING \"$dist_version\"" >>$file -echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.0-$version\"" >>$file +echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.1-$version\"" >>$file echo "#define SILC_NAME \"SILC $distribution\"" >>$file # preparing irssi -- 2.24.0