SilcUInt32 tmp_len;
bool local;
- SILC_LOG_DEBUG(("Start"));
-
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
- packet->src_id_type != SILC_ID_SERVER)
- return;
-
- if (!packet->dst_id)
+ packet->src_id_type != SILC_ID_SERVER || !packet->dst_id) {
+ SILC_LOG_DEBUG(("Bad notify packet received"));
return;
+ }
/* If the packet is destined directly to a client then relay the packet
before processing it. */
if (!channel_id)
goto out;
- if (!server->standalone)
- silc_server_packet_send_dest(server, server->router->connection,
- packet->type, packet->flags |
- SILC_PACKET_FLAG_BROADCAST,
- channel_id, SILC_ID_CHANNEL,
- packet->buffer->data,
- packet->buffer->len, FALSE);
+ silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server),
+ packet->type, packet->flags |
+ SILC_PACKET_FLAG_BROADCAST,
+ channel_id, SILC_ID_CHANNEL,
+ packet->buffer->data,
+ packet->buffer->len, FALSE);
silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
channel_id, SILC_ID_CHANNEL,
FALSE, TRUE);
} else {
/* Packet is destined to client or server */
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data, packet->buffer->len,
- FALSE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data, packet->buffer->len,
+ FALSE);
silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
server->stat.cell_clients--;
SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+ 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_check_watcher_list(server, client, NULL,
SILC_NOTIFY_TYPE_SIGNOFF);
+ /* Remove this client from watcher list if it is */
+ silc_server_del_from_watcher_list(server, client);
+
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
break;
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
}
- if (channel->topic && !strcmp(channel->topic, tmp))
+ if (channel->topic && !strcmp(channel->topic, tmp)) {
+ SILC_LOG_DEBUG(("Topic is already set and same"));
goto out;
+ }
if (client) {
/* Get user's channel entry and check that topic set is allowed. */
channel->topic = strdup(tmp);
/* Send the same notify to the channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
silc_free(channel_id);
/*
* Distribute the notify to local clients on the channel
*/
-
+
SILC_LOG_DEBUG(("CMODE CHANGE notify"));
-
+
/* Get client ID */
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
SILC_GET32_MSB(mode, tmp);
/* Check if mode changed */
- if (channel->mode == mode)
+ if (channel->mode == mode) {
+ SILC_LOG_DEBUG(("Mode is changed already"));
+
+ /* If this mode change has founder mode then we'll enforce the
+ change so that the server gets the real founder public key */
+ if (server->server_type != SILC_SERVER &&
+ sock != SILC_PRIMARY_ROUTE(server) &&
+ mode & SILC_CHANNEL_MODE_FOUNDER_AUTH && channel->founder_key) {
+ SILC_LOG_DEBUG(("Sending founder public key to server"));
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ channel->mode, server->id,
+ SILC_ID_SERVER, channel->cipher,
+ channel->hmac_name,
+ channel->passphrase,
+ channel->founder_key);
+ }
+
+ /* If we received same mode from our primary check whether founder
+ mode and key in the notify is set. We update the founder key
+ here since we may have wrong one */
+ if (server->server_type == SILC_SERVER &&
+ sock == SILC_PRIMARY_ROUTE(server) &&
+ mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+ SILC_LOG_DEBUG(("Founder public key received from primary router"));
+ tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
+ if (!tmp)
+ 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);
+ }
+
break;
+ }
/* Get user's channel entry and check that mode change is allowed */
if (client) {
goto out;
if (!silc_server_check_cmode_rights(server, channel, chl, mode)) {
SILC_LOG_DEBUG(("CMODE change is not allowed"));
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ channel->mode, server->id,
+ SILC_ID_SERVER, channel->cipher,
+ channel->hmac_name,
+ channel->passphrase,
+ channel->founder_key);
goto out;
}
} else {
+ /* Assure that server is not removing founder mode from us */
if (server->server_type == SILC_ROUTER &&
+ sock != SILC_PRIMARY_ROUTE(server) &&
channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH &&
!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
silc_server_send_notify_cmode(server, sock, FALSE, channel,
channel->mode, server->id,
- SILC_ID_SERVER,
- channel->cipher,
+ SILC_ID_SERVER, channel->cipher,
channel->hmac_name,
channel->passphrase,
channel->founder_key);
goto out;
}
- }
- /* Send the same notify to the channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, packet->buffer->data,
- packet->buffer->len, FALSE);
+ /* If server is adding founder mode, check whether there is founder
+ on channel already and is not from this server */
+ if (server->server_type == SILC_ROUTER &&
+ sock != SILC_PRIMARY_ROUTE(server) &&
+ mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+ silc_hash_table_list(channel->user_list, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chl))
+ if (chl->mode & SILC_CHANNEL_UMODE_CHANFO &&
+ chl->client->router != sock->user_data) {
+ SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ channel->mode, server->id,
+ SILC_ID_SERVER, channel->cipher,
+ channel->hmac_name,
+ channel->passphrase,
+ channel->founder_key);
+ silc_hash_table_list_reset(&htl);
+ goto out;
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+ }
/* If the channel had private keys set and the mode was removed then
we must re-generate and re-distribute a new channel key */
channel->passphrase, NULL);
}
+ /* Send the same notify to the channel */
+ silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
/* Change mode */
channel->mode = mode;
*/
SilcChannelClientEntry chl2 = NULL;
bool notify_sent = FALSE;
-
+
SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
-
+
/* Get client ID */
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
if (!silc_server_client_on_channel(client2, channel, &chl))
goto out;
+ if (server->server_type == SILC_SERVER && chl->mode == mode) {
+ SILC_LOG_DEBUG(("Mode is changed already"));
+ break;
+ }
+
if (mode & SILC_CHANNEL_UMODE_CHANFO &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
server->server_type == SILC_ROUTER &&
- sock->user_data != server->router) {
+ sock != SILC_PRIMARY_ROUTE(server)) {
SilcPublicKey founder_key = NULL;
/* If channel doesn't have founder auth mode then it's impossible
founder at all on the channel. */
if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
/* Force the mode to not have founder mode */
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
notify_sent = TRUE;
break;
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel,
- chl, mode);
- notify_sent = TRUE;
+ /* If the founder on the channel is not the one whom has set
+ the founder mode, then it's possible that this CUMODE_CHANGE
+ is correct. Due to netsplits it's possible that this
+ situation happens. */
+ if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
+ (channel->founder_key && chl2->client->data.public_key &&
+ silc_pkcs_public_key_compare(
+ channel->founder_key,
+ chl2->client->data.public_key))) {
+ chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel,
+ chl, mode);
+ notify_sent = TRUE;
+ }
break;
}
silc_hash_table_list_reset(&htl);
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
&founder_key)) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
notify_sent = TRUE;
break;
if (client && client->data.public_key &&
!silc_pkcs_public_key_compare(channel->founder_key,
client->data.public_key)) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ chl->mode = 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;
+ chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
notify_sent = TRUE;
break;
silc_pkcs_public_key_free(founder_key);
}
- if (server->server_type == SILC_ROUTER && chl->mode == mode) {
+ if (server->server_type != SILC_SERVER && chl->mode == mode) {
SILC_LOG_DEBUG(("Mode is changed already"));
break;
}
- SILC_LOG_DEBUG(("Changing the channel user mode"));
+ SILC_LOG_DEBUG(("Changing %s channel user mode",
+ chl->client->nickname ? chl->client->nickname :
+ (unsigned char *)""));
/* Change the mode */
chl->mode = mode;
/* Send the same notify to the channel */
if (!notify_sent)
- silc_server_packet_send_to_channel(server, sock, channel,
+ silc_server_packet_send_to_channel(server, NULL, channel,
packet->type,
FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
/* Re-announce our clients on the channel as the ID has changed now */
silc_server_announce_get_channel_users(server, channel, &modes, &users,
&users_modes);
+ if (users) {
+ silc_buffer_push(users, users->data - users->head);
+ silc_server_packet_send(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ users->data, users->len, FALSE);
+ silc_buffer_free(users);
+ }
if (modes) {
silc_buffer_push(modes, modes->data - modes->head);
silc_server_packet_send_dest(server, sock,
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,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users->data, users->len, FALSE);
- silc_buffer_free(users);
- }
if (users_modes) {
silc_buffer_push(users_modes, users_modes->data - users_modes->head);
silc_server_packet_send_dest(server, sock,
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
/* If the the client is not in local list we check global list */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ client_id, TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ client_id, TRUE, &cache);
if (!client) {
silc_free(client_id);
goto out;
silc_free(client_id);
/* Killer must be router operator */
- if (!(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+ if (server->server_type != SILC_SERVER &&
+ !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
SILC_LOG_DEBUG(("Killing is not allowed"));
goto out;
}
FALSE);
/* Check if anyone is watching this nickname */
- if (server->server_type == SILC_ROUTER)
- silc_server_check_watcher_list(server, client, NULL,
- SILC_NOTIFY_TYPE_KILLED);
+ silc_server_check_watcher_list(server, client, NULL,
+ SILC_NOTIFY_TYPE_KILLED);
+
+ /* Update statistics */
+ server->stat.clients--;
+ if (server->stat.cell_clients)
+ server->stat.cell_clients--;
+ SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+ if (SILC_IS_LOCAL(client)) {
+ server->stat.my_clients--;
+ silc_schedule_task_del_by_context(server->schedule, client);
+ silc_idlist_del_data(client);
+ client->mode = 0;
+ }
+
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
break;
}
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
+ SILC_LOG_DEBUG(("Notify for unknown channel"));
silc_free(channel_id);
goto out;
}
client_id, client, 0, NULL);
/* Notify our router about new client on the SILC network */
- if (!server->standalone)
- silc_server_send_new_id(server, (SilcSocketConnection)
- server->router->connection,
- server->server_type == SILC_ROUTER ? TRUE : FALSE,
- client->id, SILC_ID_CLIENT, id_len);
+ silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server), client->id,
+ SILC_ID_CLIENT, id_len);
/* Distribute to backup routers */
if (server->server_type == SILC_ROUTER) {
to our router. If we are normal server we won't send anything
since this connection must be our router connection. */
if (server->server_type == SILC_ROUTER && !server->standalone &&
- server->router->connection != sock)
- silc_server_send_new_id(server, server->router->connection,
+ SILC_PRIMARY_ROUTE(server) != sock)
+ silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server),
TRUE, new_server->id, SILC_ID_SERVER,
silc_id_get_len(server_id, SILC_ID_SERVER));
id_type == SILC_ID_SERVER &&
server->id_entry->server_type != SILC_BACKUP_ROUTER) {
id_list = server->global_list;
- router_sock = server->router ? server->router->connection : sock;
+ router_sock = server->router ? SILC_PRIMARY_ROUTE(server) : sock;
}
} else {
void *sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New ID List packet"));
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data,
- packet->buffer->len, FALSE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data,
+ packet->buffer->len, FALSE);
silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
SilcServerEntry server_entry;
SilcChannelEntry channel;
- SILC_LOG_DEBUG(("Processing New Channel"));
-
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
packet->src_id_type != SILC_ID_SERVER ||
server->server_type == SILC_SERVER)
/* If the channel does not exist, then create it. This creates a new
key to the channel as well that we will send to the server. */
if (!channel) {
+ SILC_LOG_DEBUG(("Channel is new to us"));
+
/* The protocol says that the Channel ID's IP address must be based
on the router's IP address. Check whether the ID is based in our
IP and if it is not then create a new ID and enforce the server
return;
}
channel->disabled = TRUE;
+ channel->mode = silc_channel_get_mode(payload);
/* Send the new channel key to the server */
id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
We also create a new key for the channel. */
SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
+ SILC_LOG_DEBUG(("Channel already exists"));
+
if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
/* They don't match, send CHANNEL_CHANGE notify to the server to
force the ID change. */
return;
}
-#if 0 /* Lets expect that server send CMODE_CHANGE notify anyway to
- (attempt) force mode change, and may very well get it. */
+#if 0 /* We will announce our CMODE anyway for this channel, so no need
+ to check it (implicit enforce). */
/* If the mode is different from what we have then enforce the
mode change. */
users on the channel "joining" the channel. */
silc_server_announce_get_channel_users(server, channel, &modes, &users,
&users_modes);
+ if (users) {
+ silc_buffer_push(users, users->data - users->head);
+ silc_server_packet_send(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ users->data, users->len, FALSE);
+ silc_buffer_free(users);
+ }
if (modes) {
silc_buffer_push(modes, modes->data - modes->head);
silc_server_packet_send_dest(server, sock,
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,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users->data, users->len, FALSE);
- silc_buffer_free(users);
- }
if (users_modes) {
silc_buffer_push(users_modes, users_modes->data - users_modes->head);
silc_server_packet_send_dest(server, sock,
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data,
- packet->buffer->len, FALSE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data,
+ packet->buffer->len, FALSE);
silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
}
SilcChannelClientEntry chl;
SilcServerResumeResolve r;
- SILC_LOG_DEBUG(("Start"));
-
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING(&id_string, &id_len),
SILC_STR_END);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
return;
}
r->server = server;
r->sock = silc_socket_dup(sock);
r->packet = silc_packet_context_dup(packet);
- r->data = silc_id_dup(client_id, SILC_ID_CLIENT);
+ r->data = client_id;
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
server->cmd_ident,
silc_server_command_resume_resolve, r);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
}
return;
}
r->server = server;
r->sock = silc_socket_dup(sock);
r->packet = silc_packet_context_dup(packet);
- r->data = silc_id_dup(client_id, SILC_ID_CLIENT);
+ r->data = client_id;
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
server->cmd_ident,
silc_server_command_resume_resolve, r);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
return;
}
}
resolve it first. */
if (!detached_client->data.public_key) {
if (server->server_type == SILC_SERVER && server->standalone) {
+ SILC_LOG_ERROR(("Detached client's public key not present, "
+ "closing connection"));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
} else {
/* We must retrieve the detached client's public key by sending
GETKEY command. Reprocess this packet after receiving the key */
SILC_LOG_DEBUG(("Resolving client public key"));
silc_server_send_command(server, dest_sock ? dest_sock :
- server->router->connection,
+ SILC_PRIMARY_ROUTE(server),
SILC_COMMAND_GETKEY, ++server->cmd_ident,
1, 1, idp->data, idp->len);
r = silc_calloc(1, sizeof(*r));
- if (!r)
+ if (!r) {
+ silc_free(client_id);
return;
+ }
r->server = server;
r->sock = silc_socket_dup(sock);
silc_buffer_free(idp);
}
+ silc_free(client_id);
return;
} else if (!silc_pkcs_public_key_compare(detached_client->data.public_key,
idata->public_key)) {
/* We require that the connection and resuming authentication data
must be using same key pair. */
+ SILC_LOG_ERROR(("Resuming attempted with wrong public key, "
+ "closing connection"));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
return;
}
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Resuming not possible");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_free(client_id);
return;
}
SILC_STR_END);
/* Send to primary router */
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- SILC_PACKET_RESUME_CLIENT, 0,
- buf->data, buf->len, TRUE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ SILC_PACKET_RESUME_CLIENT, 0,
+ buf->data, buf->len, TRUE);
/* As router we must deliver this packet directly to the original
server whom this client was earlier. */
/* If the ID is not based in our ID then change it */
if (!SILC_ID_COMPARE(client->id, server->id, server->id->ip.data_len)) {
+ silc_free(client_id);
while (!silc_id_create_client_id(server, server->id, server->rng,
server->md5hash, client->nickname,
&client_id)) {
if (nickfail > 9) {
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_NICKNAME, NULL);
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
return;
}
snprintf(&client->nickname[strlen(client->nickname) - 1], 1,
if (nick_change) {
/* Notify about Client ID change, nickname doesn't actually change. */
- if (!server->standalone)
- silc_server_send_notify_nick_change(server, server->router->connection,
- FALSE, client->id, client_id,
- client->nickname);
+ silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server),
+ client->id, client_id,
+ client->nickname);
}
/* Resolve users on those channels that client has joined but we
SILC_LOG_DEBUG(("Resolving users for %s channel",
channel->channel_name));
if (channel->disabled || !channel->users_resolved) {
- silc_server_send_command(server, server->router->connection,
+ silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
SILC_COMMAND_USERS, ++server->cmd_ident,
1, 2, channel->channel_name,
strlen(channel->channel_name));
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
keyp->data, keyp->len, FALSE);
- if (created && server->server_type == SILC_SERVER &&
- !server->standalone)
- silc_server_packet_send(server, server->router->connection,
+ 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);
SilcServerEntry server_entry;
SilcServerID *server_id;
- if (!client_id)
+ if (!client_id) {
+ SILC_LOG_DEBUG(("Malformed resuming packet"));
return;
+ }
/* Get entry to the client, and resolve it if we don't have it. */
detached_client = silc_idlist_find_client_by_id(server->local_list,
if (!detached_client) {
detached_client = silc_idlist_find_client_by_id(server->global_list,
client_id, TRUE, NULL);
- if (!detached_client)
+ if (!detached_client) {
+ SILC_LOG_DEBUG(("Resuming client is unknown"));
+ silc_free(client_id);
return;
+ }
}
/* Check that the client has not been resumed already because it is
/* The client is clearly attempting to resume more than once and
perhaps playing around by resuming from several different places
at the same time. */
+ SILC_LOG_DEBUG(("Attempting to re-resume client, killing both"));
silc_server_kill_client(server, detached_client, NULL,
server->id, SILC_ID_SERVER);
+ silc_free(client_id);
return;
}
/* Check whether client is detached at all */
- if (!(detached_client->mode & SILC_UMODE_DETACHED))
+ if (!(detached_client->mode & SILC_UMODE_DETACHED)) {
+ SILC_LOG_DEBUG(("Client is not detached"));
+ silc_free(client_id);
return;
+ }
/* Client is detached, and now it is resumed. Remove the detached
mode and mark that it is resumed. */
/* Get the new owner of the resumed client */
server_id = silc_id_str2id(packet->src_id, packet->src_id_len,
packet->src_id_type);
- if (!server_id)
+ if (!server_id) {
+ silc_free(client_id);
return;
+ }
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
local = FALSE;
if (!server_entry) {
silc_free(server_id);
+ silc_free(client_id);
return;
}
}
server->global_list->clients,
detached_client->nickname,
detached_client->id, detached_client, FALSE, NULL);
+ detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
/* Change the owner of the client if needed */
if (detached_client->router != server_entry)
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
- if (!server->standalone)
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,