if (!client)
return;
- SILC_LOG_DEBUG(("Remove client from all channels"));
+ SILC_LOG_DEBUG(("Remove client %s from all channels",
+ client->nickname ? client->nickname :
+ (unsigned char *)""));
if (silc_hash_table_find(clients, client, NULL, NULL))
silc_hash_table_del(clients, client);
client = (SilcClientEntry)id_cache->context;
/* If client is not registered, is not originated from `router'
- or is not owned by `entry', skip it. */
+ and is not owned by `entry', skip it. */
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
client->router != router ||
(router != entry && !SILC_ID_COMPARE(client->id, entry->id,
client = (SilcClientEntry)id_cache->context;
/* If client is not registered, is not originated from `router'
- or is not owned by `entry', skip it. */
+ and is not owned by `entry', skip it. */
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
client->router != router ||
(router != entry && !SILC_ID_COMPARE(client->id, entry->id,
SILC_PACKET_NOTIFY, 0, FALSE,
not->data, not->len, FALSE);
+ /* Send notify also to local backup routers */
+ silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
+ not->data, not->len, FALSE, TRUE);
+
silc_buffer_free(args);
silc_buffer_free(not);
for (i = 0; i < argc; i++)
}
/* Do not send the channel key if private channel key mode is set */
- if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
+ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
continue;
silc_server_send_channel_key(server, NULL, channel,
static SilcServerEntry
silc_server_update_clients_by_real_server(SilcServer server,
SilcServerEntry from,
+ SilcServerEntry to,
SilcClientEntry client,
bool local,
SilcIDCacheEntry client_cache)
SilcServerEntry server_entry;
SilcIDCacheEntry id_cache = NULL;
SilcIDCacheList list;
+ bool tolocal = (to == server->id_entry);
if (!silc_idcache_get_all(server->local_list->servers, &list))
return NULL;
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
if (server_entry != from &&
+ (tolocal || server_entry != server->id_entry) &&
SILC_ID_COMPARE(server_entry->id, client->id,
client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found (local) %s",
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
- if (server_entry != from &&
+ if (server_entry != from && server_entry != server->id_entry &&
+ (tolocal || server_entry != server->id_entry) &&
SILC_ID_COMPARE(server_entry->id, client->id,
client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found (global) %s",
if (local) {
SILC_LOG_DEBUG(("Moving client to global list"));
silc_idcache_add(server->global_list->clients, client_cache->name,
- client_cache->id, client_cache->context,
- client_cache->expire, NULL);
+ client_cache->id, client_cache->context, 0, NULL);
silc_idcache_del_by_context(server->local_list->clients, client);
}
server_entry = server_entry->router;
if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
SILC_LOG_DEBUG(("Moving client to global list"));
silc_idcache_add(server->global_list->clients, client_cache->name,
- client_cache->id, client_cache->context,
- client_cache->expire, NULL);
+ client_cache->id, client_cache->context, 0, NULL);
silc_idcache_del_by_context(server->local_list->clients, client);
}
}
if (client->router == from) {
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, from, client,
- local, id_cache);
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
if (!client->router) {
if (server->server_type == SILC_ROUTER)
client->router = from;
if (client->router)
SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_CLIENT)));
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
if (!silc_idcache_list_next(list, &id_cache))
break;
if (client->router == from) {
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, from, client,
- local, id_cache);
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
if (!client->router)
client->router = from;
} else {
if (client->router)
SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_CLIENT)));
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
if (!silc_idcache_list_next(list, &id_cache))
break;
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
- if (!chl->client->router) {
+ if (SILC_IS_LOCAL(chl->client)) {
silc_hash_table_list_reset(&htl);
return TRUE;
}
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your connection is secured with %s cipher, "
"key length %d bits",
- idata->send_key->cipher->name,
- idata->send_key->cipher->key_len));
+ silc_cipher_get_name(idata->send_key),
+ silc_cipher_get_key_len(idata->send_key)));
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your current nickname is %s",
client->nickname));
/* Remove the client from all channels. This generates new keys to the
channels as well. */
silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
- NULL, TRUE);
+ NULL, TRUE, FALSE);
/* Remove the client entry, If it is locally connected then we will also
disconnect the client here */
SilcClientEntry entry = context;
SilcSocketConnection sock;
+ if (!context)
+ return;
+
if (entry == notify->client)
return;
return NULL;
}
+
+/* This function can be used to match the invite and ban lists. */
+
+bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+ SilcUInt8 type, void *check)
+{
+ unsigned char *tmp = NULL;
+ SilcUInt32 len = 0, t;
+ SilcHashTableList htl;
+ SilcBuffer entry, idp = NULL;
+ bool ret = FALSE;
+
+ if (type < 1 || type > 3 || !check)
+ return FALSE;
+
+ if (type == 1) {
+ tmp = strdup((char *)check);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 2) {
+ tmp = silc_pkcs_public_key_encode(check, &len);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 3) {
+ idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
+ if (!idp)
+ return FALSE;
+ tmp = idp->data;
+ len = idp->len;
+ }
+
+ /* Compare the list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
+ if (type == t) {
+ if (type == 1) {
+ if (silc_string_match((char *)entry, tmp)) {
+ ret = TRUE;
+ break;
+ }
+ } else if (!memcmp(entry->data, tmp, len)) {
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ if (!idp)
+ silc_free(tmp);
+ silc_buffer_free(idp);
+ return ret;
+}
+
+/* Process invite or ban information */
+
+void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+ SilcUInt8 action, SilcArgumentPayload args)
+{
+ unsigned char *tmp;
+ SilcUInt32 type, len;
+ SilcBuffer tmp2;
+ SilcHashTableList htl;
+
+ SILC_LOG_DEBUG(("Processing invite/ban for %s action",
+ action == 0x00 ? "ADD" : "DEL"));
+
+ /* Add the information to invite list */
+ if (action == 0x00) {
+ /* Traverse all arguments and add to the hash table according to
+ their type. */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old invite string from hash table
+ and append this at the end of the existing one. */
+ char *string = NULL;
+ silc_hash_table_find(list, (void *)1,
+ NULL, (void **)&string);
+ silc_hash_table_del(list, (void *)1);
+ if (!string)
+ string = silc_calloc(len + 2, sizeof(*string));
+ else
+ string = silc_realloc(string, sizeof(*string) *
+ (strlen(string) + len + 2));
+ memset(string + strlen(string), 0, len + 2);
+ if (tmp[len - 1] == ',')
+ tmp[len - 1] = '\0';
+ strncat(string, tmp, len);
+ strncat(string, ",", 1);
+
+ /* Add new invite string to invite list */
+ silc_hash_table_add(list, (void *)1, string);
+
+ } else if (type == 2) {
+ /* Public key. Check first if the public key is already on the
+ list and ignore it if it is, otherwise, add it to hash table. */
+
+ /* Check if the public key is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new public key to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)2, tmp2);
+ }
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Check if the ID is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new Client ID to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)3, tmp2);
+ }
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+
+ /* Delete information to invite list */
+ if (action == 0x01 && list) {
+ /* Now delete the arguments from invite list */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old string from hash table and delete
+ the requested string. */
+ char *string = NULL, *start, *end, *n;
+
+ if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
+ silc_hash_table_del(list, (void *)1);
+
+ if (!strncmp(string, tmp, strlen(string) - 1)) {
+ silc_free(string);
+ string = NULL;
+ } else {
+ start = strstr(string, tmp);
+ if (start && strlen(start) >= len) {
+ end = start + len;
+ n = silc_calloc(strlen(string) - len, sizeof(*n));
+ strncat(n, string, start - string);
+ strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
+ silc_free(string);
+ string = n;
+ }
+ }
+
+ /* Add new invite string to invite list */
+ if (string)
+ silc_hash_table_add(list, (void *)1, string);
+ }
+
+ } else if (type == 2) {
+ /* Public key. */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)2, tmp2);
+ silc_buffer_free(tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)3, tmp2);
+ silc_buffer_free(tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+}