* Fixed watcher list checking during server signoff. It
crashed the server. Affected file silcd/server_util.c.
+ * The JOIN command reply returns now the founder's public
+ key. Affected file is silcd/command.c.
+
+ * Announce the channel mode, and the mode properties with
+ CMODE_CHANGE notify. Affected file silcd/server.c.
+
+ * Mark new channels by default disabled, untill at least
+ one user joins the channel. Affected file is
+ silcd/packet_receive.c.
+
Thu May 16 13:05:13 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
* The nickname argument to watch notify can be optional.
char check[512], check2[512];
bool founder = FALSE;
bool resolve;
+ unsigned char *fkey = NULL;
+ SilcUInt32 fkey_len = 0;
SILC_LOG_DEBUG(("Start"));
silc_free(tmp);
}
+ if (channel->founder_key)
+ fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
- SILC_STATUS_OK, 0, ident, 13,
+ SILC_STATUS_OK, 0, ident, 14,
2, channel->channel_name,
strlen(channel->channel_name),
3, chidp->data, chidp->len,
12, tmp3, 4,
13, user_list->data, user_list->len,
14, mode_list->data,
- mode_list->len);
+ mode_list->len,
+ 15, fkey, fkey_len);
/* Send command reply */
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
notify the mode change to the channel. */
if (founder) {
SILC_PUT32_MSB(chl->mode, mode);
- tmp = silc_pkcs_public_key_encode(channel->founder_key, &tmp_len);
silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
clidp->data, clidp->len,
mode, 4, clidp->data, clidp->len,
- tmp, tmp_len);
- silc_free(tmp);
+ fkey, fkey_len);
/* Set CUMODE notify type to network */
if (!server->standalone)
silc_buffer_free(keyp);
silc_buffer_free(user_list);
silc_buffer_free(mode_list);
+ silc_free(fkey);
out:
silc_free(passphrase);
}
if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
- !silc_hash_table_count(channel->user_list))
+ !channel->disabled && !silc_hash_table_count(channel->user_list))
created = TRUE;
}
char *channel_name, *tmp;
SilcUInt32 mode, created;
SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
+ SilcPublicKey founder_key = NULL;
COMMAND_CHECK_STATUS;
silc_buffer_pull_tail(client_mode_list, len);
silc_buffer_put(client_mode_list, tmp, len);
+ /* Get founder key */
+ tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
+ if (tmp)
+ silc_pkcs_public_key_decode(tmp, len, &founder_key);
+
/* See whether we already have the channel. */
entry = silc_idlist_find_channel_by_name(server->local_list,
channel_name, &cache);
}
}
+ if (founder_key) {
+ if (entry->founder_key)
+ silc_pkcs_public_key_free(entry->founder_key);
+ entry->founder_key = founder_key;
+ founder_key = NULL;
+ }
+
if (entry->hmac_name && hmac) {
silc_free(entry->hmac_name);
entry->hmac_name = strdup(silc_hmac_get_name(hmac));
silc_free(client_id);
silc_server_command_reply_free(cmd);
+ silc_pkcs_public_key_free(founder_key);
if (client_id_list)
silc_buffer_free(client_id_list);
if (client_mode_list)
silc_hash_table_add(client->channels, channel, chl);
silc_free(client_id);
channel->user_count++;
+ channel->disabled = FALSE;
break;
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- } else if (!client->data.public_key) {
+ } else if (client && !client->data.public_key) {
client->data.public_key =
silc_pkcs_public_key_copy(channel->founder_key);
}
server->server_type == SILC_ROUTER) {
/* Check whether this client is allowed to be channel founder on
this channel. */
- SilcPublicKey founder_key;
+ SilcPublicKey founder_key = NULL;
/* If channel doesn't have founder auth mode then it's impossible
that someone would be getting founder rights with CUMODE command.
break;
}
- /* Now match the public key we have cached and publick key sent.
+ /* Now match the public key we have cached and public key sent.
They must match. */
- if (!silc_pkcs_public_key_compare(channel->founder_key,
+ if (client->data.public_key &&
+ !silc_pkcs_public_key_compare(channel->founder_key,
client->data.public_key)) {
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
notify_sent = TRUE;
break;
}
+ if (!silc_pkcs_public_key_compare(channel->founder_key,
+ founder_key)) {
+ mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
+
+ if (founder_key)
+ silc_pkcs_public_key_free(founder_key);
}
SILC_LOG_DEBUG(("Changing the channel user mode"));
}
if (channel_id2) {
- SilcBuffer users = NULL, users_modes = NULL;
+ SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
/* Re-announce this channel which ID was changed. */
silc_server_send_new_channel(server, sock, FALSE, channel->channel_name,
channel->mode);
/* Re-announce our clients on the channel as the ID has changed now */
- silc_server_announce_get_channel_users(server, channel, &users,
+ silc_server_announce_get_channel_users(server, channel, &modes, &users,
&users_modes);
+ if (modes) {
+ silc_buffer_push(modes, modes->data - modes->head);
+ silc_server_packet_send_dest(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel->id, SILC_ID_CHANNEL,
+ modes->data, modes->len, FALSE);
+ silc_buffer_free(modes);
+ }
if (users) {
silc_buffer_push(users, users->data - users->head);
silc_server_packet_send(server, sock,
0, channel_id, sock->user_data, NULL, NULL, 0);
if (!channel)
return;
+ channel->disabled = TRUE;
server->stat.channels++;
if (server->server_type == SILC_ROUTER)
silc_free(channel_id);
return;
}
+ channel->disabled = TRUE;
+#if 0
+ /* CMODE change notify is expected */
/* Get the mode and set it to the channel */
channel->mode = silc_channel_get_mode(payload);
+#endif
/* Send the new channel key to the server */
id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
/* The channel exist by that name, check whether the ID's match.
If they don't then we'll force the server to use the ID we have.
We also create a new key for the channel. */
- SilcBuffer users = NULL, users_modes = NULL;
+ SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
/* They don't match, send CHANNEL_CHANGE notify to the server to
/* Since the channel is coming from server and we also know about it
then send the JOIN notify to the server so that it see's our
users on the channel "joining" the channel. */
- silc_server_announce_get_channel_users(server, channel, &users,
+ silc_server_announce_get_channel_users(server, channel, &modes, &users,
&users_modes);
+ if (modes) {
+ silc_buffer_push(modes, modes->data - modes->head);
+ silc_server_packet_send_dest(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel->id, SILC_ID_CHANNEL,
+ modes->data, modes->len, FALSE);
+ silc_buffer_free(modes);
+ }
if (users) {
silc_buffer_push(users, users->data - users->head);
silc_server_packet_send(server, sock,
void silc_server_announce_get_channel_users(SilcServer server,
SilcChannelEntry channel,
+ SilcBuffer *channel_modes,
SilcBuffer *channel_users,
SilcBuffer *channel_users_modes)
{
int len;
unsigned char mode[4], *fkey = NULL;
SilcUInt32 fkey_len = 0;
+ char *hmac;
SILC_LOG_DEBUG(("Start"));
- /* Now find all users on the channel */
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+
+ /* CMODE notify */
+ clidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
+ SILC_PUT32_MSB(channel->mode, mode);
+ hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
+ if (channel->founder_key)
+ fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+ tmp =
+ silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
+ 6, clidp->data, clidp->len,
+ mode, sizeof(mode),
+ NULL, 0,
+ hmac, hmac ? strlen(hmac) : 0,
+ channel->passphrase,
+ channel->passphrase ?
+ strlen(channel->passphrase) : 0,
+ fkey, fkey_len);
+ len = tmp->len;
+ *channel_modes =
+ silc_buffer_realloc(*channel_modes,
+ (*channel_modes ?
+ (*channel_modes)->truelen + len : len));
+ silc_buffer_pull_tail(*channel_modes,
+ ((*channel_modes)->end -
+ (*channel_modes)->data));
+ silc_buffer_put(*channel_modes, tmp->data, tmp->len);
+ silc_buffer_pull(*channel_modes, len);
+ silc_buffer_free(tmp);
+ silc_buffer_free(clidp);
+ silc_free(fkey);
+
+ /* Now find all users on the channel */
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
void silc_server_announce_get_channels(SilcServer server,
SilcIDList id_list,
SilcBuffer *channels,
+ SilcBuffer **channel_modes,
SilcBuffer *channel_users,
SilcBuffer **channel_users_modes,
SilcUInt32 *channel_users_modes_c,
sizeof(**channel_users_modes) *
(i + 1));
(*channel_users_modes)[i] = NULL;
+ *channel_modes = silc_realloc(*channel_modes,
+ sizeof(**channel_modes) * (i + 1));
+ (*channel_modes)[i] = NULL;
*channel_ids = silc_realloc(*channel_ids,
sizeof(**channel_ids) * (i + 1));
(*channel_ids)[i] = NULL;
silc_server_announce_get_channel_users(server, channel,
+ &(*channel_modes)[i],
channel_users,
&(*channel_users_modes)[i]);
(*channel_ids)[i] = channel->id;
unsigned long creation_time,
SilcSocketConnection remote)
{
- SilcBuffer channels = NULL, channel_users = NULL;
+ SilcBuffer channels = NULL, *channel_modes = NULL, channel_users = NULL;
SilcBuffer *channel_users_modes = NULL;
SilcBuffer *channel_topics = NULL;
SilcUInt32 channel_users_modes_c = 0;
/* Get channels and channel users in local list */
silc_server_announce_get_channels(server, server->local_list,
- &channels, &channel_users,
+ &channels, &channel_modes,
+ &channel_users,
&channel_users_modes,
&channel_users_modes_c,
&channel_topics,
/* Get channels and channel users in global list */
if (server->server_type != SILC_SERVER)
silc_server_announce_get_channels(server, server->global_list,
- &channels, &channel_users,
+ &channels, &channel_modes,
+ &channel_users,
&channel_users_modes,
&channel_users_modes_c,
&channel_topics,
silc_buffer_free(channels);
}
+ if (channel_modes) {
+ int i;
+
+ for (i = 0; i < channel_users_modes_c; i++) {
+ if (!channel_modes[i])
+ continue;
+ silc_buffer_push(channel_modes[i],
+ channel_modes[i]->data -
+ channel_modes[i]->head);
+ SILC_LOG_HEXDUMP(("channel modes"), channel_modes[i]->data,
+ channel_modes[i]->len);
+ silc_server_packet_send_dest(server, remote,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel_ids[i], SILC_ID_CHANNEL,
+ channel_modes[i]->data,
+ channel_modes[i]->len,
+ FALSE);
+ silc_buffer_free(channel_modes[i]);
+ }
+ silc_free(channel_modes);
+ }
+
if (channel_users) {
silc_buffer_push(channel_users, channel_users->data - channel_users->head);
SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
SilcBuffer *topic);
void silc_server_announce_get_channel_users(SilcServer server,
SilcChannelEntry channel,
+ SilcBuffer *channel_modes,
SilcBuffer *channel_users,
SilcBuffer *channel_users_modes);
void silc_server_announce_get_channels(SilcServer server,
SilcIDList id_list,
SilcBuffer *channels,
+ SilcBuffer **channel_modes,
SilcBuffer *channel_users,
SilcBuffer **channel_users_modes,
SilcUInt32 *channel_users_modes_c,
if (is_op && is_fo)
return TRUE;
+ /* Founder emplies operator */
+ if (is_fo)
+ is_op = TRUE;
+
/* We know that client is channel operator, check that they are not
changing anything that requires channel founder rights. Rest of the
modes are available automatically for channel operator. */
.ds RF FORMFEED[Page %]
.ds CF
.ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
.ds CH
.na
.hy 0
.nf
Network Working Group P. Riikonen
Internet-Draft
-draft-riikonen-silc-commands-03.txt 15 May 2002
-Expires: 15 November 2002
+draft-riikonen-silc-commands-04.txt XXX
+Expires: XXX
.in 3
.ce 2
SILC Commands
-<draft-riikonen-silc-commands-03.txt>
+<draft-riikonen-silc-commands-04.txt>
.ti 0
Status of this Memo
Reply messages to the command:
- Max Arguments: 14
+ Max Arguments: 15
Arguments: (1) <Status Payload> (2) <channel>
(3) <Channel ID> (4) <Client ID>
(5) <channel mode mask> (6) <created>
(9) [<invite list>] (10) [<topic>]
(11) [<hmac>] (12) <list count>
(13) <Client ID list> (14) <client mode list>
+ (15) [<founder pubkey>]
This command replies with the channel name requested by the
client, channel ID of the channel and topic of the channel
the clients currently on the channel and their modes on the
channel. The <Client ID list> is formed by adding the ID Payloads
one after the other. The <client mode list> is formed by adding
- 32 bit MSB first order values one after the other.
+ 32 bit MSB first order values one after the other. The <founder
+ pubkey> is the public key of the channel founder.
Client receives the channel key in the reply message as well
inside <Channel Key Payload>.
EMail: priikone@iki.fi
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires XXX
.ti 0
.ds RF FORMFEED[Page %]
.ds CF
.ds LH Internet Draft
-.ds RH 15 May 2002
+.ds RH XXX
.ds CH
.na
.hy 0
.nf
Network Working Group P. Riikonen
Internet-Draft
-draft-riikonen-silc-spec-05.txt 15 May 2002
-Expires: 15 November 2002
+draft-riikonen-silc-spec-06.txt XXX
+Expires: XXX
.in 3
.ce 3
Secure Internet Live Conferencing (SILC),
Protocol Specification
-<draft-riikonen-silc-spec-05.txt>
+<draft-riikonen-silc-spec-06.txt>
.ti 0
Status of this Memo
All clients are announced by compiling a list of ID Payloads into the
SILC_PACKET_NEW_ID packet. All channels are announced by compiling a
-list of Channel Payloads into the SILC_PACKET_NEW_CHANNEL packet. Also,
-the channel users on the channels must be announced by compiling a
+list of Channel Payloads into the SILC_PACKET_NEW_CHANNEL packet.
+Channels' mode and founder public key and other channel mode specific
+data is announced by sending SILC_NOTIFY_TYPE_CMODE_CHANGE notify list.
+Also, the channel users on the channels must be announced by compiling a
list of Notify Payloads with the SILC_NOTIFY_TYPE_JOIN notify type into
the SILC_PACKET_NOTIFY packet. The users' modes on the channel must
also be announced by compiling list of Notify Payloads with the
EMail: priikone@iki.fi
-This Internet-Draft expires 15 November 2002
+This Internet-Draft expires XXX
}
argc = silc_argument_get_arg_num(cmd->args);
- if (argc < 7 || argc > 14) {
+ if (argc < 7 || argc > 15) {
SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Cannot join channel: Bad reply packet");
COMMAND_REPLY_ERROR;