silc_schedule_task_del_by_context(server->schedule, client);
/* Remove the client from all channels. */
- silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, FALSE);
+ silc_server_remove_from_channels(server, NULL, client, TRUE,
+ tmp, FALSE, FALSE);
/* Check if anyone is watching this nickname */
if (server->server_type == SILC_ROUTER)
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+ silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+ &channel->founder_key);
}
break;
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+ silc_pkcs_public_key_payload_decode(tmp, tmp_len, &channel->founder_key);
if (!channel->founder_key ||
(client && client->data.public_key &&
if (channel->founder_key) {
/* Get public key that must be present in notify */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
- &founder_key)) {
+ if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+ &founder_key)) {
chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
notify_sent = TRUE;
/* Now match the public key we have cached and public key sent.
They must match. */
+#if 0 /* The key may be other than the client's in 1.2 */
if (client && client->data.public_key &&
!silc_pkcs_public_key_compare(channel->founder_key,
client->data.public_key)) {
notify_sent = TRUE;
break;
}
+#endif
if (!silc_pkcs_public_key_compare(channel->founder_key,
founder_key)) {
chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
goto out;
}
- /* Get the added invite */
+ /* Get the invite action */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (tmp) {
- if (!channel->invite_list)
- channel->invite_list = silc_calloc(tmp_len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (tmp_len +
- strlen(channel->invite_list) +
- 2));
- if (tmp[tmp_len - 1] == ',')
- tmp[tmp_len - 1] = '\0';
-
- strncat(channel->invite_list, tmp, tmp_len);
- strncat(channel->invite_list, ",", 1);
- }
+ if (tmp && tmp_len == 1) {
+ SilcUInt8 action = (SilcUInt8)tmp[0];
+ SilcUInt16 iargc = 0;
+ SilcArgumentPayload iargs;
+
+ /* Get invite list */
+ tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
+ if (!tmp || tmp_len < 2)
+ goto out;
- /* Get the deleted invite */
- tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
- if (tmp && channel->invite_list) {
- char *start, *end, *n;
-
- if (!strncmp(channel->invite_list, tmp,
- strlen(channel->invite_list) - 1)) {
- silc_free(channel->invite_list);
- channel->invite_list = NULL;
- } else {
- start = strstr(channel->invite_list, tmp);
- if (start && strlen(start) >= tmp_len) {
- end = start + tmp_len;
- n = silc_calloc(strlen(channel->invite_list) - tmp_len, sizeof(*n));
- strncat(n, channel->invite_list, start - channel->invite_list);
- strncat(n, end + 1, ((channel->invite_list +
- strlen(channel->invite_list)) - end) - 1);
- silc_free(channel->invite_list);
- channel->invite_list = n;
- }
- }
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(iargc, tmp);
+ iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+ if (!iargs)
+ goto out;
+
+ if (action == 0 && !channel->invite_list)
+ channel->invite_list =
+ silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ silc_server_inviteban_destruct, channel, TRUE);
+
+ /* Proces the invite action */
+ silc_server_inviteban_process(server, channel->invite_list, action,
+ iargs);
+ silc_argument_payload_free(iargs);
}
break;
/* Remove the client from all channels. */
silc_server_remove_from_channels(server, NULL, client,
- TRUE, NULL, FALSE);
+ TRUE, NULL, FALSE, FALSE);
/* Check if anyone is watching this nickname */
if (server->server_type == SILC_ROUTER)
}
silc_free(server_id);
- /* Sending SERVER_SIGNOFF is not right way to signoff local connection */
- if (SILC_IS_LOCAL(server_entry))
+ /* For local entrys SERVER_SIGNOFF is processed only on backup router.
+ It is possible that router sends server signoff for a server. If
+ backup router has it as local connection it will be closed. */
+ if (SILC_IS_LOCAL(server_entry)) {
+ if (server->server_type == SILC_BACKUP_ROUTER) {
+ sock = server_entry->connection;
+ SILC_LOG_DEBUG(("Closing connection %s after SERVER_SIGNOFF",
+ sock->hostname));
+ SILC_SET_DISCONNECTING(sock);
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_close_connection(server, sock);
+ }
+
break;
+ }
/* Remove all servers that are originated from this server, and
remove the clients of those servers too. */
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
goto out;
- /* From protocol version 1.1 we get the kicker's ID as well. */
+ /* Get the kicker's Client ID */
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 (!tmp)
+ goto out;
+ 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,
+ /* 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) {
- 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);
-
- /* Kicker must be operator on channel */
- if (!silc_server_client_on_channel(client2, channel, &chl))
- goto out;
- if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
- !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
- SILC_LOG_DEBUG(("Kicking is not allowed"));
+ 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_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+ SILC_LOG_DEBUG(("Kicking is not allowed"));
+ goto out;
+ }
/* Send to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
+ /* Remove the client from channel's invite list */
+ if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
+ SilcBuffer ab;
+ SilcArgumentPayload iargs;
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ ab = silc_argument_payload_encode_one(NULL, tmp, tmp_len, 3);
+ iargs = silc_argument_payload_parse(ab->data, ab->len, 1);
+ silc_server_inviteban_process(server, channel->invite_list, 1, iargs);
+ silc_buffer_free(ab);
+ silc_argument_payload_free(iargs);
+ }
+
/* Remove the client from channel */
silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
if (comment_len > 128)
comment_len = 127;
- /* From protocol version 1.1 we get the killer's ID as well. */
+ /* Get the killer's Client ID */
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (tmp) {
- client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!client_id)
- goto out;
+ if (!tmp)
+ goto out;
+ client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+ if (!client_id)
+ goto out;
- if (id_type == SILC_ID_CLIENT) {
- /* If the the client is not in local list we check global list */
- client2 = silc_idlist_find_client_by_id(server->global_list,
+ if (id_type == SILC_ID_CLIENT) {
+ /* 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) {
- 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 (server->server_type != SILC_SERVER &&
- !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
- SILC_LOG_DEBUG(("Killing is not allowed"));
+ silc_free(client_id);
goto out;
}
}
+ silc_free(client_id);
+
+ /* Killer must be router operator */
+ if (server->server_type != SILC_SERVER &&
+ !(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
/* Remove the client from all channels */
silc_server_remove_from_channels(server, NULL, client, FALSE, NULL,
- FALSE);
+ FALSE, TRUE);
/* Check if anyone is watching this nickname */
silc_server_check_watcher_list(server, client, NULL,
}
silc_free(channel_id);
- /* Get the new ban and add it to the ban list */
+ /* Get the ban action */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (tmp) {
- if (!channel->ban_list)
- channel->ban_list = silc_calloc(tmp_len + 2,
- sizeof(*channel->ban_list));
- else
- channel->ban_list = silc_realloc(channel->ban_list,
- sizeof(*channel->ban_list) *
- (tmp_len +
- strlen(channel->ban_list) + 2));
- strncat(channel->ban_list, tmp, tmp_len);
- strncat(channel->ban_list, ",", 1);
- }
+ if (tmp && tmp_len == 1) {
+ SilcUInt8 action = (SilcUInt8)tmp[0];
+ SilcUInt16 iargc = 0;
+ SilcArgumentPayload iargs;
- /* Get the ban to be removed and remove it from the list */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (tmp && channel->ban_list) {
- char *start, *end, *n;
-
- if (!strncmp(channel->ban_list, tmp, strlen(channel->ban_list) - 1)) {
- silc_free(channel->ban_list);
- channel->ban_list = NULL;
- } else {
- start = strstr(channel->ban_list, tmp);
- if (start && strlen(start) >= tmp_len) {
- end = start + tmp_len;
- n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
- strncat(n, channel->ban_list, start - channel->ban_list);
- strncat(n, end + 1, ((channel->ban_list +
- strlen(channel->ban_list)) - end) - 1);
- silc_free(channel->ban_list);
- channel->ban_list = n;
- }
- }
+ /* Get ban list */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (!tmp || tmp_len < 2)
+ goto out;
+
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(iargc, tmp);
+ iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+ if (!iargs)
+ goto out;
+
+ if (action == 0 && !channel->ban_list)
+ channel->ban_list =
+ silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ silc_server_inviteban_destruct, channel, TRUE);
+
+ /* Proces the ban action */
+ silc_server_inviteban_process(server, channel->ban_list, action,
+ iargs);
+ silc_argument_payload_free(iargs);
}
break;
client_id, FALSE, NULL);
if (client) {
silc_server_remove_from_channels(server, NULL, client, TRUE,
- NULL, TRUE);
+ NULL, TRUE, FALSE);
silc_idlist_del_data(client);
silc_idlist_del_client(server->global_list, client);
}
/* Save the channel key */
channel = silc_server_save_channel_key(server, buffer, NULL);
- if (!channel)
+ if (!channel) {
+ SILC_LOG_ERROR(("Bad channel key from %s (%s)",
+ sock->hostname, sock->ip));
return;
-
+ }
+
/* Distribute the key to everybody who is on the channel. If we are router
we will also send it to locally connected servers. */
silc_server_send_channel_key(server, sock, channel, FALSE);
return NULL;
}
+ /* Make sure this client hasn't registered already */
+ if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ return NULL;
+ }
+
/* Parse incoming packet */
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING_ALLOC(&username,
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
client->nickname = nickname;
client->username = username;
- client->userinfo = realname ? realname : strdup(" ");
+ client->userinfo = realname ? realname : strdup(username);
client->id = client_id;
id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
local = FALSE;
}
+ /* Make sure this server hasn't registered already */
+ if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ return NULL;
+ }
+
/* Parse the incoming packet */
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
server_entry = silc_idlist_find_server_by_id(server->local_list,
server_id, TRUE, NULL);
if (server_entry) {
- silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ if (SILC_IS_LOCAL(server_entry)) {
+ silc_server_disconnect_remote(server, server_entry->connection,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (((SilcSocketConnection)server_entry->connection)->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ } else {
+ silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ }
} else {
server_entry = silc_idlist_find_server_by_id(server->global_list,
server_id, TRUE, NULL);
- if (server_entry)
- silc_idcache_del_by_context(server->global_list->servers, server_entry);
+ if (server_entry) {
+ if (SILC_IS_LOCAL(server_entry)) {
+ silc_server_disconnect_remote(server, server_entry->connection,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (((SilcSocketConnection)server_entry->connection)->user_data)
+ silc_server_free_sock_user_data(server, server_entry->connection,
+ NULL);
+ } else {
+ silc_idcache_del_by_context(server->global_list->servers,
+ server_entry);
+ }
+ }
}
/* Update server entry */
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
new_server->server_name = server_name;
new_server->id = server_id;
-
+
SILC_LOG_DEBUG(("New server id(%s)",
silc_id_render(server_id, SILC_ID_SERVER)));
silc_free(channel_id);
- /* Update statistics */
- server->stat.channels++;
- server->stat.cell_channels++;
-
/* 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_idlist_add_data(detached_client, idata);
detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+ detached_client->data.status |= SILC_IDLIST_STATUS_LOCAL;
detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES;
detached_client->mode &= ~SILC_UMODE_DETACHED;
server->stat.my_detached--;
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_RESUME_CLIENT, 0,
buf->data, buf->len, TRUE);
+ silc_server_backup_send(server, detached_client->router,
+ SILC_PACKET_RESUME_CLIENT, 0,
+ buf->data, buf->len, TRUE, TRUE);
/* As router we must deliver this packet directly to the original
server whom this client was earlier. */
server->stat.clients--;
if (server->stat.cell_clients)
server->stat.cell_clients--;
- silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE);
+ silc_server_remove_from_channels(server, NULL, client, FALSE,
+ NULL, FALSE, FALSE);
silc_server_del_from_watcher_list(server, client);
if (!silc_idlist_del_client(server->local_list, client))
silc_idlist_del_client(server->global_list, client);
channel->key_len / 8, channel->key);
silc_free(id_string);
- /* Send the key packet to client */
+ /* Send the channel key to the client */
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
keyp->data, keyp->len, FALSE);
- if (created && server->server_type == SILC_SERVER)
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- SILC_PACKET_CHANNEL_KEY, 0,
- keyp->data, keyp->len, FALSE);
+ /* Distribute the channel key to channel */
+ if (created) {
+ silc_server_send_channel_key(server, NULL, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
+ keyp->data, keyp->len, FALSE, TRUE);
+ }
silc_buffer_free(keyp);
}
/* Client is detached, and now it is resumed. Remove the detached
mode and mark that it is resumed. */
+ silc_idlist_del_data(detached_client);
detached_client->mode &= ~SILC_UMODE_DETACHED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
id_cache->expire = 0;
- /* Update channel information regarding global clients on channel. */
- if (server->server_type == SILC_SERVER) {
- silc_hash_table_list(detached_client->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&chl))
- chl->channel->global_users =
- silc_server_channel_has_global(chl->channel);
- silc_hash_table_list_reset(&htl);
- }
-
silc_schedule_task_del_by_context(server->schedule, detached_client);
/* Get the new owner of the resumed client */
}
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER &&
server_entry->server_type == SILC_ROUTER)
local = FALSE;
detached_client))
silc_idcache_del_by_context(server->global_list->clients,
detached_client);
- silc_idcache_add(local && server->server_type == SILC_ROUTER ?
- server->local_list->clients :
- server->global_list->clients,
+ silc_idcache_add(local && server->server_type == SILC_ROUTER ?
+ server->local_list->clients :
+ server->global_list->clients,
detached_client->nickname,
detached_client->id, detached_client, FALSE, NULL);
/* Change the owner of the client */
detached_client->router = server_entry;
+ /* Update channel information regarding global clients on channel. */
+ if (server->server_type != SILC_ROUTER) {
+ silc_hash_table_list(detached_client->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl))
+ chl->channel->global_users =
+ silc_server_channel_has_global(chl->channel);
+ silc_hash_table_list_reset(&htl);
+ }
+
silc_free(server_id);
}