/* Remove the client from all channels. */
silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, 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_SIGNOFF);
+
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
break;
/* 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) {
+ if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Topic change is not allowed"));
goto out;
}
nickname = silc_argument_get_arg_type(args, 3, &nickname_len);;
/* Replace the Client ID */
- client = silc_idlist_replace_client_id(server->global_list, client_id,
+ client = silc_idlist_replace_client_id(server,
+ server->global_list, client_id,
client_id2, nickname);
if (!client)
- client = silc_idlist_replace_client_id(server->local_list, client_id,
+ client = silc_idlist_replace_client_id(server,
+ server->local_list, client_id,
client_id2, nickname);
if (client) {
/* Set the HMAC key out of current channel key. The client must do
this locally. */
silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
- channel->key_len / 8,
- hash);
+ channel->key_len / 8, hash);
silc_hmac_set_key(channel->hmac, hash,
silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
if (client != client2) {
/* Sender must be operator */
- if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
+ if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("CUMODE change is not allowed"));
goto out;
}
/* 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) {
+ if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Inviting is not allowed"));
goto out;
}
silc_server_remove_from_channels(server, NULL, client,
TRUE, NULL, 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_SERVER_SIGNOFF);
+
+ /* Remove this client from watcher list if it is */
+ if (local)
+ silc_server_del_from_watcher_list(server, client);
+
/* Remove the client */
silc_idlist_del_client(local ? server->local_list :
server->global_list, client);
/* Kicker must be operator on channel */
if (!silc_server_client_on_channel(client2, channel, &chl))
goto out;
- if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
+ if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Kicking is not allowed"));
goto out;
}
silc_server_remove_from_channels(server, NULL, client, FALSE, NULL,
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);
+
break;
}
/* Change the mode */
client->mode = mode;
+ /* Check if anyone is watching this nickname */
+ if (server->server_type == SILC_ROUTER)
+ silc_server_check_watcher_list(server, client, NULL,
+ SILC_NOTIFY_TYPE_UMODE_CHANGE);
+
break;
case SILC_NOTIFY_TYPE_BAN:
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
if (!channel) {
- SILC_LOG_DEBUG(("Could not find channel"));
+ SilcBuffer idp;
+ unsigned char error;
+
+ /* Send SILC_NOTIFY_TYPE_ERROR to indicate that such destination ID
+ does not exist or is invalid. */
+ idp = silc_id_payload_encode_data(packet->dst_id,
+ packet->dst_id_len,
+ packet->dst_id_type);
+ if (!idp)
+ goto out;
+
+ error = SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID;
+ if (packet->src_id_type == SILC_ID_CLIENT) {
+ SilcClientID *client_id = silc_id_str2id(packet->src_id,
+ packet->src_id_len,
+ packet->src_id_type);
+ silc_server_send_notify_dest(server, sock, FALSE,
+ client_id, SILC_ID_CLIENT,
+ SILC_NOTIFY_TYPE_ERROR, 2,
+ &error, 1, idp->data, idp->len);
+ silc_free(client_id);
+ } else {
+ silc_server_send_notify(server, sock, FALSE,
+ SILC_NOTIFY_TYPE_ERROR, 2,
+ &error, 1, idp->data, idp->len);
+ }
+
+ silc_buffer_free(idp);
goto out;
}
}
/* If channel is moderated check that client is allowed to send
messages. */
- if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chl->mode) {
+ if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Channel is silenced from normal users"));
goto out;
}
/* Remove the old cache entry. */
if (!silc_idcache_del_by_context(server->local_list->clients, client)) {
SILC_LOG_INFO(("Unauthenticated client attempted to register to network"));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "You have not been authenticated");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL);
return NULL;
}
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
"connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Incomplete client information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ NULL);
return NULL;
}
silc_free(realname);
SILC_LOG_ERROR(("Client %s (%s) did not send its username, closing "
"connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Incomplete client information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ NULL);
return NULL;
}
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
"connection", sock->hostname, sock->ip));
silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete client information");
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ NULL);
return NULL;
}
SILC_LOG_ERROR(("Client %s (%s) sent incomplete information, closing "
"connection", sock->hostname, sock->ip));
silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete client information");
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ NULL);
return NULL;
}
nickfail++;
if (nickfail > 9) {
silc_server_disconnect_remote(server, sock,
- "Server closed connection: Bad nickname");
+ SILC_STATUS_ERR_BAD_NICKNAME, NULL);
return NULL;
}
snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
/* Send some nice info to the client */
silc_server_send_connect_notifys(server, sock, client);
+ /* Check if anyone is watching this nickname */
+ if (server->server_type == SILC_ROUTER)
+ silc_server_check_watcher_list(server, client, NULL, 0);
+
return client;
}
SILC_LOG_INFO(("Unauthenticated %s attempted to register to "
"network", (sock->type == SILC_SOCKET_TYPE_SERVER ?
"server" : "router")));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "You have not been authenticated");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL);
return NULL;
}
local = FALSE;
if (!silc_id_is_valid_server_id(server, server_id, sock)) {
SILC_LOG_INFO(("Invalid server ID sent by %s (%s)",
sock->ip, sock->hostname));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Your Server ID is not valid");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_BAD_SERVER_ID, NULL);
silc_free(server_name);
return NULL;
}
if (sock->type == SILC_SOCKET_TYPE_SERVER)
server->stat.cell_clients++;
server->stat.clients++;
+
+ /* Check if anyone is watching this nickname */
+ if (server->server_type == SILC_ROUTER && id_list == server->local_list)
+ silc_server_check_watcher_list(server, entry, NULL, 0);
}
break;
if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
goto out;
}
if (!client) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
goto out;
}
}
if (!(client->mode & SILC_UMODE_DETACHED)) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
goto out;
}
}
if (!client_id || auth_len < 128) {
SILC_LOG_ERROR(("Client %s (%s) sent incomplete resume information, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
return;
}
} else {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
}
return;
}
if (server->server_type == SILC_SERVER) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
return;
}
}
resolve it first. */
if (!detached_client->data.public_key) {
if (server->standalone) {
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
} else {
/* We must retrieve the detached client's public key by sending
GETKEY command. Reprocess this packet after receiving the key */
idata->public_key)) {
/* We require that the connection and resuming authentication data
must be using same key pair. */
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
return;
}
SILC_ID_CLIENT)) {
SILC_LOG_ERROR(("Client %s (%s) resume authentication failed, "
"closing connection", sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Incomplete resume information");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Resuming not possible");
return;
}
nickfail++;
if (nickfail > 9) {
silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Bad nickname");
+ SILC_STATUS_ERR_BAD_NICKNAME, NULL);
return;
}
snprintf(&client->nickname[strlen(client->nickname) - 1], 1,