SilcChannelID *channel_id = NULL, *channel_id2;
SilcClientID *client_id, *client_id2;
SilcServerID *server_id;
- SilcChannelEntry channel;
- SilcClientEntry client;
- SilcServerEntry server_entry;
+ SilcIdType id_type;
+ SilcChannelEntry channel = NULL;
+ SilcClientEntry client = NULL, client2 = NULL;
+ SilcServerEntry server_entry = NULL;
SilcChannelClientEntry chl;
SilcIDCacheEntry cache;
SilcHashTableList htl;
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp)
goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id)
goto out;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
break;
/* Do not add client to channel if it is there already */
- if (silc_server_client_on_channel(client, channel)) {
+ if (silc_server_client_on_channel(client, channel, NULL)) {
SILC_LOG_DEBUG(("Client already on channel"));
break;
}
silc_free(channel_id);
goto out;
}
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id) {
silc_free(channel_id);
goto out;
silc_free(client_id);
/* Check if on channel */
- if (!silc_server_client_on_channel(client, channel))
+ if (!silc_server_client_on_channel(client, channel, NULL))
break;
/* Send the leave notify to channel */
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
SILC_LOG_DEBUG(("TOPIC SET notify"));
+ /* 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 entry */
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+
if (!channel_id) {
channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
packet->dst_id_type);
goto out;
}
+ /* Get user's channel entry and check that topic set is allowed. */
+ if (!silc_server_client_on_channel(client, channel, &chl))
+ goto out;
+ if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
+ channel->mode & SILC_CHANNEL_MODE_TOPIC)
+ goto out;
+
+ /* Set the topic for channel */
silc_free(channel->topic);
channel->topic = strdup(tmp);
id = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!id)
goto out;
- client_id = silc_id_payload_parse_id(id, tmp_len);
+ client_id = silc_id_payload_parse_id(id, tmp_len, NULL);
if (!client_id)
goto out;
id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!id2)
goto out;
- client_id2 = silc_id_payload_parse_id(id2, tmp_len);
+ client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
if (!client_id2)
goto out;
SILC_LOG_DEBUG(("CMODE CHANGE notify"));
+ /* 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, &id_type);
+ if (!client_id)
+ goto out;
+
+ /* Get client entry */
+ if (id_type == SILC_ID_CLIENT) {
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+ }
+
if (!channel_id) {
channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
packet->dst_id_type);
goto out;
}
}
+ silc_free(channel_id);
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp) {
- silc_free(channel_id);
+ if (!tmp)
goto out;
- }
-
SILC_GET32_MSB(mode, tmp);
/* Check if mode changed */
if (channel->mode == mode)
break;
+ /* Get user's channel entry and check that mode change is allowed */
+ if (client) {
+ if (!silc_server_client_on_channel(client, channel, &chl))
+ goto out;
+ if (!silc_server_check_cmode_rights(server, channel, chl, mode))
+ goto out;
+ }
+
/* Send the same notify to the channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
FALSE, packet->buffer->data,
/* Change mode */
channel->mode = mode;
- silc_free(channel_id);
/* Get the hmac */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
+ /* 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, &id_type);
+ if (!client_id)
+ goto out;
+
+ /* Get client entry */
+ if (id_type == SILC_ID_CLIENT) {
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+ }
+
if (!channel_id) {
channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
packet->dst_id_type);
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
if (!tmp)
goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
/* Get client entry */
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
- if (!client) {
- client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
- if (!client) {
+ 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);
+ if (client) {
+ /* Check that sender is on channel */
+ if (!silc_server_client_on_channel(client, channel, &chl))
+ goto out;
+
+ if (client != client2) {
+ /* Sender must be operator */
+ if (chl->mode == SILC_CHANNEL_UMODE_NONE)
+ goto out;
+
+ /* Check that target is on channel */
+ if (!silc_server_client_on_channel(client2, channel, &chl))
+ goto out;
+
+ /* If target is founder mode change is not allowed. */
+ if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
+ goto out;
+ }
+ }
+
/* Get entry to the channel user list */
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_send_notify_cumode(server, sock, FALSE, channel, mode,
- client->id, SILC_ID_CLIENT,
- client->id);
+ client2->id, SILC_ID_CLIENT,
+ client2->id);
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ idp = silc_id_payload_encode(client2->id, SILC_ID_CLIENT);
SILC_PUT32_MSB(mode, cumode);
silc_server_send_notify_to_channel(server, sock, channel, FALSE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE,
}
}
- if (chl->client == client) {
+ if (chl->client == client2) {
if (chl->mode == mode) {
notify_sent = TRUE;
break;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id)
goto out;
}
silc_free(channel_id);
- /* Get the added invite */
+ /* Get client ID */
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (!tmp)
+ goto out;
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+ if (!client_id)
+ goto out;
+
+ /* Get client entry */
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+
+ /* Get user's channel entry and check that inviting is allowed. */
+ if (!silc_server_client_on_channel(client, channel, &chl))
+ goto out;
+ if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
+ channel->mode & SILC_CHANNEL_MODE_INVITE)
+ goto out;
+
+ /* Get the added invite */
+ tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
if (tmp) {
if (!channel->invite_list)
channel->invite_list = silc_calloc(tmp_len + 2,
}
/* Get the deleted invite */
- tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+ tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
if (tmp && channel->invite_list) {
char *start, *end, *n;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id)
goto out;
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp)
goto out;
- channel_id2 = silc_id_payload_parse_id(tmp, tmp_len);
+ channel_id2 = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id2)
goto out;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- server_id = silc_id_payload_parse_id(tmp, tmp_len);
+ server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!server_id)
goto out;
tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
if (!tmp)
continue;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
continue;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
goto out;
}
}
+ silc_free(client_id);
+
+ /* If target is founder they cannot be kicked */
+ if (!silc_server_client_on_channel(client, channel, &chl))
+ goto out;
+ 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. */
+ 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) {
+ client = 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);
+
+ /* Kicker must be operator on channel */
+ if (!silc_server_client_on_channel(client2, channel, &chl))
+ goto out;
+ if (chl->mode == SILC_CHANNEL_UMODE_NONE)
+ goto out;
+ }
/* Send to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
id = silc_argument_get_arg_type(args, 1, &id_len);
if (!id)
goto out;
- client_id = silc_id_payload_parse_id(id, id_len);
+ client_id = silc_id_payload_parse_id(id, id_len, NULL);
if (!client_id)
goto out;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
goto out;
SILC_GET32_MSB(mode, tmp);
-#define SILC_UMODE_STATS_UPDATE(oper, mod) \
-do { \
- if (client->mode & (mod)) { \
- if (!(mode & (mod))) { \
- if (client->connection) \
- server->stat.my_ ## oper ## _ops--; \
- if (server->server_type == SILC_ROUTER) \
- server->stat. oper ## _ops--; \
- } \
- } else { \
- if (mode & (mod)) { \
- if (client->connection) \
- server->stat.my_ ## oper ## _ops++; \
- if (server->server_type == SILC_ROUTER) \
- server->stat. oper ## _ops++; \
- } \
- } \
-} while(0)
-
- /* Update statistics */
- SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
- SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
+ /* Check that mode changing is allowed. */
+ if (!silc_server_check_umode_rights(server, client, mode))
+ goto out;
- /* Save the mode */
+ /* Change the mode */
client->mode = mode;
break;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
- channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!channel_id)
goto out;
{
SilcChannelEntry channel = NULL;
SilcChannelID *id = NULL;
- void *sender = NULL;
- void *sender_entry = NULL;
+ void *sender_id = NULL;
+ SilcClientEntry sender_entry = NULL;
bool local = TRUE;
SILC_LOG_DEBUG(("Processing channel message"));
/* See that this client is on the channel. If the original sender is
not client (as it can be server as well) we don't do the check. */
- sender = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!sender)
+ sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type);
+ if (!sender_id)
goto out;
if (packet->src_id_type == SILC_ID_CLIENT) {
sender_entry = silc_idlist_find_client_by_id(server->local_list,
- sender, TRUE, NULL);
+ sender_id, TRUE, NULL);
if (!sender_entry) {
local = FALSE;
sender_entry = silc_idlist_find_client_by_id(server->global_list,
- sender, TRUE, NULL);
+ sender_id, TRUE, NULL);
}
if (!sender_entry || !silc_server_client_on_channel(sender_entry,
- channel)) {
+ channel, NULL)) {
SILC_LOG_DEBUG(("Client not on channel"));
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. */
+ /* 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
+ this packet to network, and now someone is routing it back to us. */
if (server->server_type == SILC_ROUTER &&
sock->type == SILC_SOCKET_TYPE_ROUTER && local) {
SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it"));
/* Distribute the packet to our local clients. This will send the
packet for further routing as well, if needed. */
- silc_server_packet_relay_to_channel(server, sock, channel, sender,
+ silc_server_packet_relay_to_channel(server, sock, channel, sender_id,
packet->src_id_type, sender_entry,
packet->buffer->data,
packet->buffer->len, FALSE);
out:
- if (sender)
- silc_free(sender);
- if (id)
- silc_free(id);
+ silc_free(sender_id);
+ silc_free(id);
}
/* Received channel key packet. We distribute the key to all of our locally