SilcCommand command,
SilcCommandStatus status,
uint32 arg_type,
- unsigned char *arg,
+ const unsigned char *arg,
uint32 arg_len);
static bool
silc_server_command_pending_error_check(SilcServerCommandContext cmd,
silc_server_command_send_status_reply(cmd, command,
SILC_STATUS_ERR_NOT_REGISTERED);
- silc_server_command_free(cmd);
return FALSE;
}
SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
+ if (!client) {
+ silc_server_command_free(timeout->ctx);
+ silc_free(timeout);
+ }
+
/* Update access time */
client->last_command = time(NULL);
timeout->ctx,
timeout->cmd->cmd))
timeout->cmd->cb(timeout->ctx, NULL);
+ else
+ silc_server_command_free(timeout->ctx);
silc_free(timeout);
}
silc_server_command_process_timeout,
(void *)timeout,
2 - (time(NULL) - client->last_command), 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
else
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_command_process_timeout,
- (void *)timeout,
- 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ (void *)timeout, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
return;
}
cmd->cb(ctx, NULL);
else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
cmd->cb(ctx, NULL);
+ else
+ silc_server_command_free(ctx);
}
/* Allocate Command Context */
with `context' when reply has been received. It can be SILC_COMMAND_NONE
to match any command with the `ident'. If `ident' is non-zero
the `callback' will be executed when received reply with command
- identifier `ident'. */
+ identifier `ident'. If there already exists pending command for the
+ specified command, ident, callback and context this function has no
+ effect. */
-void silc_server_command_pending(SilcServer server,
+bool silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
uint16 ident,
- SilcServerPendingDestructor destructor,
SilcCommandCb callback,
void *context)
{
SilcServerCommandPending *reply;
+ /* Check whether identical pending already exists for same command,
+ ident, callback and callback context. If it does then it would be
+ error to register it again. */
+ silc_dlist_start(server->pending_commands);
+ while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
+ if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
+ reply->callback == callback && reply->context == context)
+ return FALSE;
+ }
+
reply = silc_calloc(1, sizeof(*reply));
reply->reply_cmd = reply_cmd;
reply->ident = ident;
reply->context = context;
reply->callback = callback;
- reply->destructor = destructor;
silc_dlist_add(server->pending_commands, reply);
+
+ return TRUE;
}
/* Deletes pending command by reply command type. */
callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
callbacks[i].context = r->context;
callbacks[i].callback = r->callback;
- callbacks[i].destructor = r->destructor;
ctx->ident = ident;
i++;
}
return callbacks;
}
-/* Destructor function for pending callbacks. This is called when using
- pending commands to free the context given for the pending command. */
-
-static void silc_server_command_destructor(void *context)
-{
- silc_server_command_free((SilcServerCommandContext)context);
-}
-
/* Sends simple status message as command reply packet */
static void
SilcCommand command,
SilcCommandStatus status,
uint32 arg_type,
- unsigned char *arg,
+ const unsigned char *arg,
uint32 arg_len)
{
SilcBuffer buffer;
status != SILC_STATUS_LIST_START &&
status != SILC_STATUS_LIST_ITEM &&
status != SILC_STATUS_LIST_END) {
- /* Send the error message */
- silc_server_command_send_status_reply(cmd, command, status);
+ SilcBuffer buffer;
+
+ /* Send the same command reply payload */
+ silc_command_set_ident(cmdr->payload,
+ silc_command_get_ident(cmd->payload));
+ buffer = silc_command_payload_encode_payload(cmdr->payload);
+ silc_server_packet_send(cmd->server, cmd->sock,
+ SILC_PACKET_COMMAND_REPLY, 0,
+ buffer->data, buffer->len, FALSE);
+ silc_buffer_free(buffer);
return TRUE;
}
(*client_id)[0] = silc_id_payload_parse_id(tmp, len);
if ((*client_id)[0] == NULL) {
silc_free(*client_id);
+ silc_server_command_send_status_reply(cmd, command,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
return FALSE;
}
*client_id_count = 1;
for (i = 0; i < *client_id_count; i++)
silc_free((*client_id)[i]);
silc_free(*client_id);
+ silc_server_command_send_status_reply(
+ cmd, command,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
return FALSE;
}
(*client_id_count)++;
int i, k;
bool no_res = TRUE;
+ SILC_LOG_DEBUG(("Start"));
+
for (i = 0; i < clients_count; i++) {
entry = clients[i];
-
- if (!entry || (entry->nickname && entry->username && entry->userinfo) ||
- !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- !entry->router)
+ if (!entry)
continue;
+ if ((entry->nickname && entry->username && entry->userinfo) ||
+ !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ if (!entry->router)
+ continue;
+
+ /* If we are normal server, and we've not resolved this client from
+ router and it is global client, we'll check whether it is on some
+ channel. If not then we cannot be sure about its validity, and
+ we'll resolve it from router. */
+ if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
+ entry->connection || silc_hash_table_count(entry->channels))
+ continue;
+ }
+
/* We need to resolve this entry since it is not complete */
if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
to the command reply and we're done with this one. */
silc_server_command_pending(server, SILC_COMMAND_NONE,
entry->resolve_cmd_ident,
- silc_server_command_destructor,
silc_server_command_whois,
silc_server_command_dup(cmd));
no_res = FALSE;
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
r->ident,
- silc_server_command_destructor,
silc_server_command_whois,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
SilcClientEntry *clients,
uint32 clients_count,
- int count)
+ int count,
+ const char *nickname,
+ SilcClientID **client_ids)
{
SilcServer server = cmd->server;
char *tmp;
- int i, k, len;
+ int i, k, len, valid_count;
SilcBuffer packet, idp, channels;
SilcClientEntry entry;
SilcCommandStatus status;
unsigned char *fingerprint;
SilcSocketConnection hsock;
- len = 0;
- for (i = 0; i < clients_count; i++)
+ /* Process only valid clients and ignore those that are not registered. */
+ valid_count = 0;
+ for (i = 0; i < clients_count; i++) {
if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
- len++;
+ valid_count++;
+ else
+ clients[i] = NULL;
+ }
- if (len == 0 && clients_count) {
- entry = clients[0];
- if (entry->nickname) {
+ if (!valid_count) {
+ /* No valid clients found, send error reply */
+ if (nickname) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, entry->nickname,
- strlen(entry->nickname));
- } else {
- SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+ 3, nickname, strlen(nickname));
+ } else if (client_ids && client_ids[0]) {
+ SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2, idp->data, idp->len);
silc_buffer_free(idp);
}
-
return;
}
- status = SILC_STATUS_OK;
- if (len > 1)
+ /* Start processing found clients. */
+ if (valid_count > 1)
status = SILC_STATUS_LIST_START;
+ else
+ status = SILC_STATUS_OK;
for (i = 0, k = 0; i < clients_count; i++) {
entry = clients[i];
-
- if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- if (clients_count == 1) {
- if (entry->nickname) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, entry->nickname,
- strlen(entry->nickname));
- } else {
- SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 2, idp->data, idp->len);
- silc_buffer_free(idp);
- }
- }
+ if (!entry)
continue;
- }
if (k >= 1)
status = SILC_STATUS_LIST_ITEM;
-
- if (clients_count > 1 && k == clients_count - 1)
+ if (valid_count > 1 && k == valid_count - 1)
status = SILC_STATUS_LIST_END;
-
if (count && k - 1 == count)
status = SILC_STATUS_LIST_END;
- if (count && k - 1 > count)
- break;
-
- /* Sanity check, however these should never fail. However, as
- this sanity check has been added here they have failed. */
- if (!entry->nickname || !entry->username || !entry->userinfo)
- continue;
-
/* Send WHOIS reply */
idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
tmp = silc_argument_get_first_arg(cmd->args, NULL);
}
}
+static void
+silc_server_command_whois_send_router(SilcServerCommandContext cmd)
+{
+ SilcServer server = cmd->server;
+ SilcBuffer tmpbuf;
+ uint16 old_ident;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ /* Send WHOIS command to our router */
+ silc_server_packet_send(server, (SilcSocketConnection)
+ server->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply from router */
+ silc_server_command_pending(server, SILC_COMMAND_WHOIS,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_whois,
+ silc_server_command_dup(cmd));
+ cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_buffer_free(tmpbuf);
+}
+
static int
silc_server_command_whois_process(SilcServerCommandContext cmd)
{
Since nicknames can be expanded into many clients we need to send it
to router. If the WHOIS included only client ID's we will check them
first locally since we just might have them. */
- if (nick && !client_id_count &&
- cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- server->server_type == SILC_SERVER && !cmd->pending &&
+ if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
!server->standalone) {
- SilcBuffer tmpbuf;
- uint16 old_ident;
-
- old_ident = silc_command_get_ident(cmd->payload);
- silc_command_set_ident(cmd->payload, ++server->cmd_ident);
- tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-
- /* Send WHOIS command to our router */
- silc_server_packet_send(server, (SilcSocketConnection)
- server->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
-
- /* Reprocess this packet after received reply from router */
- silc_server_command_pending(server, SILC_COMMAND_WHOIS,
- silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
- silc_server_command_whois,
- silc_server_command_dup(cmd));
- cmd->pending = TRUE;
-
- silc_command_set_ident(cmd->payload, old_ident);
-
- silc_buffer_free(tmpbuf);
+ silc_server_command_whois_send_router(cmd);
ret = -1;
goto out;
}
clients = silc_realloc(clients, sizeof(*clients) *
(clients_count + 1));
clients[clients_count++] = entry;
+ } else {
+ /* If we are normal server and did not send the request first to router
+ do it now, since we do not have the Client ID information. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_whois_send_router(cmd);
+ ret = -1;
+ goto out;
+ }
}
}
} else {
+ /* Find by nickname */
if (!silc_idlist_get_clients_by_hash(server->local_list,
nick, server->md5hash,
&clients, &clients_count))
}
if (!clients) {
+ /* If we are normal server and did not send the request first to router
+ do it now, since we do not have the information. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_whois_send_router(cmd);
+ ret = -1;
+ goto out;
+ }
+
/* Such client(s) really does not exist in the SILC network. */
if (!client_id_count) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
/* Send the command reply */
silc_server_command_whois_send_reply(cmd, clients, clients_count,
- count);
+ count, nick, client_id);
out:
if (client_id_count) {
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
ret = silc_server_command_whois_process(cmd);
-
- if (!ret)
- silc_server_command_free(cmd);
+ silc_server_command_free(cmd);
}
/******************************************************************************
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_whowas,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
-
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
/* We will take only clients that are not valid anymore. They are the
ones that are not registered anymore but still have a ID. They
have disconnected us, and thus valid for WHOWAS. */
- if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
- continue;
- if (entry->id == NULL)
+ if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
continue;
if (count && i - 1 == count)
if (clients_count > 2)
status = SILC_STATUS_LIST_ITEM;
-
if (clients_count > 1 && i == clients_count - 1)
status = SILC_STATUS_LIST_END;
- /* Sanity check, however these should never fail. However, as
- this sanity check has been added here they have failed. */
- if (!entry->nickname || !entry->username)
- continue;
-
/* Send WHOWAS reply */
idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
tmp = silc_argument_get_first_arg(cmd->args, NULL);
-
memset(uh, 0, sizeof(uh));
memset(nh, 0, sizeof(nh));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_whowas,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
-
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
silc_free(clients);
silc_free(nick);
silc_free(server_name);
-
return ret;
}
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
ret = silc_server_command_whowas_process(cmd);
-
- if (!ret)
- silc_server_command_free(cmd);
+ silc_server_command_free(cmd);
}
/******************************************************************************
******************************************************************************/
-static bool
+static void
+silc_server_command_identify_send_router(SilcServerCommandContext cmd)
+{
+ SilcServer server = cmd->server;
+ SilcBuffer tmpbuf;
+ uint16 old_ident;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ /* Send IDENTIFY command to our router */
+ silc_server_packet_send(server, (SilcSocketConnection)
+ server->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply from router */
+ silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_identify,
+ silc_server_command_dup(cmd));
+ cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_buffer_free(tmpbuf);
+}
+
+static int
silc_server_command_identify_parse(SilcServerCommandContext cmd,
SilcClientEntry **clients,
uint32 *clients_count,
uint32 *servers_count,
SilcChannelEntry **channels,
uint32 *channels_count,
- uint32 *count,
- bool *names)
+ uint32 *count)
{
SilcServer server = cmd->server;
unsigned char *tmp;
tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
if (!tmp) {
/* No ID, get the names. */
- *names = TRUE;
+
+ /* If we are normal server and have not resolved information from
+ router yet, do so now. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_identify_send_router(cmd);
+ return -1;
+ }
/* Try to get nickname@server. */
tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
silc_free(nick_server);
if (!(*clients)) {
+ /* the nickname does not exist, send error reply */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, tmp, strlen(tmp));
- return FALSE;
+ return 0;
}
}
}
if (!(*servers)) {
+ /* the server does not exist, send error reply */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_SERVER,
3, tmp, strlen(tmp));
- return FALSE;
+ return 0;
}
}
}
if (!(*channels)) {
+ /* The channel does not exist, send error reply */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3, tmp, strlen(tmp));
- return FALSE;
+ return 0;
}
}
if (!(*clients) && !(*servers) && !(*channels)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return FALSE;
+ return 0;
}
} else {
/* Command includes ID, we must use that. Also check whether the command
silc_free(*clients);
silc_free(*servers);
silc_free(*channels);
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return FALSE;
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ return 0;
}
id = silc_id_payload_get_id(idp);
(*clients_count + 1));
(*clients)[(*clients_count)++] = (SilcClientEntry)entry;
} else {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+ /* If we are normal server and have not resolved information from
+ router yet, do so now. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_identify_send_router(cmd);
+ silc_free(*clients);
+ silc_free(*servers);
+ silc_free(*channels);
+ return -1;
+ } else {
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 2, tmp, len);
- error = TRUE;
+ 2, tmp, len);
+ error = TRUE;
+ }
}
break;
(*servers_count + 1));
(*servers)[(*servers_count)++] = (SilcServerEntry)entry;
} else {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
- 2, tmp, len);
- error = TRUE;
+ /* If we are normal server and have not resolved information from
+ router yet, do so now. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_identify_send_router(cmd);
+ silc_free(*clients);
+ silc_free(*servers);
+ silc_free(*channels);
+ return -1;
+ } else {
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
+ 2, tmp, len);
+ error = TRUE;
+ }
}
break;
(*channels_count + 1));
(*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
} else {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
- 2, tmp, len);
- error = TRUE;
+ /* If we are normal server and have not resolved information from
+ router yet, do so now. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
+ !server->standalone) {
+ silc_server_command_identify_send_router(cmd);
+ silc_free(*clients);
+ silc_free(*servers);
+ silc_free(*channels);
+ return -1;
+ } else {
+ silc_server_command_send_status_data(
+ cmd, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
+ 2, tmp, len);
+ error = TRUE;
+ }
}
break;
}
else
*count = 0;
- return TRUE;
+ return 1;
}
/* Checks that all mandatory fields in client entry are present. If not
for (i = 0; i < clients_count; i++) {
entry = clients[i];
-
- if (!entry || entry->nickname ||
- !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
- !entry->router)
+ if (!entry)
continue;
+ if (entry->nickname ||
+ !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ if (!entry->router)
+ continue;
+
+ /* If we are normal server, and we've not resolved this client from
+ router and it is global client, we'll check whether it is on some
+ channel. If not then we cannot be sure about its validity, and
+ we'll resolve it from router. */
+ if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
+ entry->connection || silc_hash_table_count(entry->channels))
+ continue;
+ }
+
/* We need to resolve this entry since it is not complete */
if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
to the command reply and we're done with this one. */
silc_server_command_pending(server, SILC_COMMAND_NONE,
entry->resolve_cmd_ident,
- silc_server_command_destructor,
silc_server_command_identify,
silc_server_command_dup(cmd));
no_res = FALSE;
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
r->ident,
- silc_server_command_destructor,
silc_server_command_identify,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
int count)
{
SilcServer server = cmd->server;
- int i, k, len;
+ int i, k, len, valid_count;
SilcBuffer packet, idp;
SilcCommandStatus status;
uint16 ident = silc_command_get_ident(cmd->payload);
if (clients) {
SilcClientEntry entry;
- len = 0;
- for (i = 0; i < clients_count; i++)
+ /* Process only valid entries. */
+ valid_count = 0;
+ for (i = 0; i < clients_count; i++) {
if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
- len++;
+ valid_count++;
+ else
+ clients[i] = NULL;
+ }
+
+ if (!valid_count) {
+ /* No valid entries found at all, just send error */
+ unsigned char *tmp;
- if (len == 0 && clients_count) {
- entry = clients[0];
- if (entry->nickname) {
+ tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
+ if (tmp) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, entry->nickname,
- strlen(entry->nickname));
+ 3, tmp, strlen(tmp));
} else {
- SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+ tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 2, idp->data, idp->len);
- silc_buffer_free(idp);
+ 2, tmp, len);
}
-
return;
}
- if (len > 1)
+ /* Process all valid client entries and send command replies */
+
+ if (valid_count > 1)
status = SILC_STATUS_LIST_START;
for (i = 0, k = 0; i < clients_count; i++) {
entry = clients[i];
-
- if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- if (clients_count == 1) {
- SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
- 2, idp->data, idp->len);
- silc_buffer_free(idp);
- }
+ if (!entry)
continue;
- }
-
+
if (k >= 1)
status = SILC_STATUS_LIST_ITEM;
- if (clients_count > 1 && k == clients_count - 1
+ if (valid_count > 1 && k == valid_count - 1
&& !servers_count && !channels_count)
status = SILC_STATUS_LIST_END;
if (count && k - 1 == count)
status = SILC_STATUS_LIST_END;
if (count && k - 1 > count)
break;
-
+
/* Send IDENTIFY reply */
+
idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
-
memset(uh, 0, sizeof(uh));
memset(nh, 0, sizeof(nh));
-
strncat(nh, entry->nickname, strlen(entry->nickname));
if (!strchr(entry->nickname, '@')) {
strncat(nh, "@", 1);
server->server_name, len);
}
}
-
+
if (!entry->username) {
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
status, ident, 2,
}
}
- status = (status == SILC_STATUS_LIST_ITEM ?
- SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
-
if (servers) {
SilcServerEntry entry;
}
}
- status = (status == SILC_STATUS_LIST_ITEM ?
- SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
-
if (channels) {
SilcChannelEntry entry;
static int
silc_server_command_identify_process(SilcServerCommandContext cmd)
{
- SilcServer server = cmd->server;
uint32 count = 0;
int ret = 0;
SilcClientEntry *clients = NULL;
SilcServerEntry *servers = NULL;
SilcChannelEntry *channels = NULL;
uint32 clients_count = 0, servers_count = 0, channels_count = 0;
- bool names;
/* Parse the IDENTIFY request */
- if (!silc_server_command_identify_parse(cmd,
- &clients, &clients_count,
- &servers, &servers_count,
- &channels, &channels_count,
- &count, &names))
- return 0;
-
- /* Send the IDENTIFY request to the router only if it included nickname.
- Since nicknames can be expanded into many clients we need to send it
- to router. If the IDENTIFY included only client ID's we will check them
- first locally since we just might have them. */
- if (names && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- server->server_type == SILC_SERVER && !cmd->pending &&
- !server->standalone) {
- SilcBuffer tmpbuf;
- uint16 old_ident;
-
- old_ident = silc_command_get_ident(cmd->payload);
- silc_command_set_ident(cmd->payload, ++server->cmd_ident);
- tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-
- /* Send IDENTIFY command to our router */
- silc_server_packet_send(server, (SilcSocketConnection)
- server->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
-
- /* Reprocess this packet after received reply from router */
- silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
- silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
- silc_server_command_identify,
- silc_server_command_dup(cmd));
- cmd->pending = TRUE;
-
- silc_command_set_ident(cmd->payload, old_ident);
-
- silc_buffer_free(tmpbuf);
- ret = -1;
- goto out;
- }
+ ret = silc_server_command_identify_parse(cmd,
+ &clients, &clients_count,
+ &servers, &servers_count,
+ &channels, &channels_count,
+ &count);
+ if (ret < 1)
+ return ret;
+ ret = 0;
/* Check that all mandatory fields are present and request those data
from the server who owns the client if necessary. */
silc_free(clients);
silc_free(servers);
silc_free(channels);
-
return ret;
}
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
ret = silc_server_command_identify_process(cmd);
-
- if (!ret)
- silc_server_command_free(cmd);
-}
-
-/* Checks string for bad characters and returns TRUE if they are found. */
-
-static int silc_server_command_bad_chars(char *nick)
-{
- int i;
-
- for (i = 0; i < strlen(nick); i++) {
- if (!isascii(nick[i]))
- return TRUE;
- if (nick[i] <= 32) return TRUE;
- if (nick[i] == ' ') return TRUE;
- if (nick[i] == '*') return TRUE;
- if (nick[i] == '?') return TRUE;
- if (nick[i] == ',') return TRUE;
- }
-
- return FALSE;
+ silc_server_command_free(cmd);
}
/* Server side of command NICK. Sets nickname for user. Setting
SilcServer server = cmd->server;
SilcBuffer packet, nidp, oidp = NULL;
SilcClientID *new_id;
+ uint32 nick_len;
char *nick;
uint16 ident = silc_command_get_ident(cmd->payload);
int nickfail = 0;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
/* Check nickname */
- nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
- if (silc_server_command_bad_chars(nick) == TRUE) {
+ nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
+ if (nick_len > 128)
+ nick[128] = '\0';
+ if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
SILC_STATUS_ERR_BAD_NICKNAME);
goto out;
}
- if (strlen(nick) > 128)
- nick[128] = '\0';
-
/* Check for same nickname */
if (!strcmp(client->nickname, nick)) {
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Update client cache */
silc_idcache_add(server->local_list->clients, client->nickname,
- client->id, (void *)client, FALSE);
+ client->id, (void *)client, 0, NULL);
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
SilcChannelEntry *gch,
uint32 gch_count)
{
- int i;
+ int i, k;
SilcBuffer packet, idp;
SilcChannelEntry entry;
SilcCommandStatus status;
char *topic;
unsigned char usercount[4];
uint32 users;
+ int valid_lcount = 0, valid_rcount = 0;
- for (i = 0; i < lch_count; i++)
+ for (i = 0; i < lch_count; i++) {
if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
lch[i] = NULL;
- for (i = 0; i < gch_count; i++)
+ else
+ valid_lcount++;
+ }
+ for (i = 0; i < gch_count; i++) {
if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
gch[i] = NULL;
+ else
+ valid_rcount++;
+ }
status = SILC_STATUS_OK;
if ((lch_count + gch_count) > 1)
status = SILC_STATUS_LIST_START;
/* Local list */
- for (i = 0; i < lch_count; i++) {
+ for (i = 0, k = 0; i < lch_count; i++) {
entry = lch[i];
if (!entry)
continue;
- if (i >= 1)
+ if (k >= 1)
status = SILC_STATUS_LIST_ITEM;
- if (i >= 1 && i == lch_count - 1 && !gch_count)
+ if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
status = SILC_STATUS_LIST_END;
idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
packet->len, FALSE);
silc_buffer_free(packet);
silc_buffer_free(idp);
+ k++;
}
/* Global list */
- for (i = 0; i < gch_count; i++) {
+ for (i = 0, k = 0; i < gch_count; i++) {
entry = gch[i];
if (!entry)
continue;
- if (i >= 1)
+ if (k >= 1)
status = SILC_STATUS_LIST_ITEM;
- if (i >= 1 && i == gch_count - 1)
+ if (valid_rcount > 1 && k == valid_rcount - 1)
status = SILC_STATUS_LIST_END;
idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
packet->len, FALSE);
silc_buffer_free(packet);
silc_buffer_free(idp);
+ k++;
}
}
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_LIST,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_list,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
/* Get Channel ID */
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send notify about topic change to all clients on the channel */
- silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+ silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
SILC_NOTIFY_TYPE_TOPIC_SET, 2,
idp->data, idp->len,
channel->topic, strlen(channel->topic));
tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
if (tmp) {
char invite[512];
+ bool resolve;
dest_id = silc_id_payload_parse_id(tmp, len);
if (!dest_id) {
}
/* Get the client entry */
- dest = silc_server_get_client_resolve(server, dest_id);
+ dest = silc_server_get_client_resolve(server, dest_id, &resolve);
if (!dest) {
- if (server->server_type != SILC_SERVER) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+ if (server->server_type != SILC_SERVER || !resolve) {
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
goto out;
}
receiving the reply to the query. */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
server->cmd_ident,
- silc_server_command_destructor,
silc_server_command_invite,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_free(channel_id);
silc_free(dest_id);
- return;
+ goto out;
}
/* Check whether the requested client is already on the channel. */
SilcClientID *client_id;
unsigned char *tmp, *comment;
uint32 tmp_len, tmp_len2;
+ bool local;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
/* Get the client entry */
remote_client = silc_idlist_find_client_by_id(server->local_list,
client_id, TRUE, NULL);
+ local = TRUE;
if (!remote_client) {
remote_client = silc_idlist_find_client_by_id(server->global_list,
client_id, TRUE, NULL);
+ local = FALSE;
if (!remote_client) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
silc_server_close_connection(server, sock);
} else {
+ /* Update statistics */
+ if (remote_client->connection)
+ server->stat.my_clients--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_clients--;
+ SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
+
/* Remove remote client */
- if (!silc_idlist_del_client(server->global_list, remote_client))
- silc_idlist_del_client(server->local_list, remote_client);
+ silc_idlist_del_client(local ? server->local_list :
+ server->global_list, remote_client);
}
out:
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_INFO,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_info,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
if (!entry && !cmd->pending && !server->standalone) {
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_INFO,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_info,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
}
uint16 ident = silc_command_get_ident(cmd->payload);
char check[512], check2[512];
bool founder = FALSE;
+ bool resolve;
SILC_LOG_DEBUG(("Start"));
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
client = (SilcClientEntry)sock->user_data;
} else {
- client = silc_server_get_client_resolve(server, client_id);
+ client = silc_server_get_client_resolve(server, client_id, &resolve);
if (!client) {
if (cmd->pending)
goto out;
+ if (!resolve) {
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+
/* The client info is being resolved. Reprocess this packet after
receiving the reply to the query. */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
- server->cmd_ident, NULL,
+ server->cmd_ident,
silc_server_command_join,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
- return;
+ goto out;
}
cmd->pending = FALSE;
username and/or hostname is in the ban list the access to the
channel is denied. */
if (channel->ban_list) {
- if (!channel->ban_list ||
- silc_string_match(channel->ban_list, check) ||
+ if (silc_string_match(channel->ban_list, check) ||
silc_string_match(channel->ban_list, check2)) {
silc_server_command_send_status_reply(
cmd, SILC_COMMAND_JOIN,
}
if (!passphrase || !channel->passphrase ||
- memcmp(channel->passphrase, passphrase,
- strlen(channel->passphrase))) {
+ memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_PASSWORD);
goto out;
}
channel_name = tmp;
- if (strlen(channel_name) > 256)
+ if (tmp_len > 256)
channel_name[255] = '\0';
- if (silc_server_command_bad_chars(channel_name) == TRUE) {
+ if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_CHANNEL);
goto out;
channel_name, NULL);
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- /* If this is coming from client the Client ID in the command packet must
- be same as the client's ID. */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
- if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
- }
+ SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
+ client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
if (!channel || channel->disabled) {
/* Channel not found */
channel = silc_server_create_new_channel(server, server->id, cipher,
hmac, channel_name, TRUE);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
goto out;
}
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_JOIN,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_join,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
- return;
+ silc_command_set_ident(cmd->payload, old_ident);
+ goto out;
}
/* We are router and the channel does not seem exist so we will check
if (cmd->pending && context2) {
SilcServerCommandReplyContext reply =
(SilcServerCommandReplyContext)context2;
+
if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
SILC_GET32_MSB(created, tmp);
- create_key = FALSE; /* Router returned the key already */
+ if (silc_argument_get_arg_type(reply->args, 7, NULL)
+ create_key = FALSE; /* Router returned the key already */
}
+
+ if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
+ !silc_hash_table_count(channel->user_list))
+ created = TRUE;
}
/* If the channel does not have global users and is also empty the client
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_MOTD,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_motd,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
if (!entry && !cmd->pending && !server->standalone) {
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_MOTD,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_motd,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
if (!entry) {
goto out;
}
} else {
- if (client->mode & SILC_UMODE_SERVER_OPERATOR)
- /* Remove the server operator rights */
+ /* Remove the server operator rights */
+ if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
+ if (client->connection)
+ server->stat.my_server_ops--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.server_ops--;
+ }
}
if (mask & SILC_UMODE_ROUTER_OPERATOR) {
goto out;
}
} else {
- if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
- /* Remove the router operator rights */
+ /* Remove the router operator rights */
+ if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
+ if (client->connection)
+ server->stat.my_router_ops--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.router_ops--;
+ }
}
if (mask & SILC_UMODE_GONE) {
/* The mode is removed and we need to generate and distribute
new channel key. Clients are not using private channel keys
anymore after this. */
-
+
/* Re-generate channel key */
if (!silc_server_create_channel_key(server, channel, 0))
goto out;
-
+
/* Send the channel key. This sends it to our local clients and if
we are normal server to our router as well. */
silc_server_send_channel_key(server, NULL, channel,
server->server_type == SILC_ROUTER ?
FALSE : !server->standalone);
-
+
cipher = channel->channel_key->cipher->name;
hmac = (char *)silc_hmac_get_name(channel->hmac);
}
}
-
+
if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
/* User limit is set on channel */
uint32 user_limit;
/* If the target client is founder, no one else can change their mode
but themselves. */
- if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
+ if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
- SILC_STATUS_ERR_NOT_YOU);
+ SILC_STATUS_ERR_NO_CHANNEL_PRIV);
goto out;
}
silc_server_send_notify_kicked(server, server->router->connection,
server->server_type == SILC_ROUTER ?
TRUE : FALSE, channel,
- target_client->id, comment);
+ target_client->id, client->id, comment);
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
/* Re-generate channel key */
/* Client is now server operator */
client->mode |= SILC_UMODE_SERVER_OPERATOR;
+ /* Update statistics */
+ if (client->connection)
+ server->stat.my_server_ops++;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.server_ops++;
+
/* Send UMODE change to primary router */
if (!server->standalone)
silc_server_send_notify_umode(server, server->router->connection, TRUE,
/* Client is now router operator */
client->mode |= SILC_UMODE_ROUTER_OPERATOR;
+ /* Update statistics */
+ if (client->connection)
+ server->stat.my_router_ops++;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.router_ops++;
+
/* Send UMODE change to primary router */
if (!server->standalone)
silc_server_send_notify_umode(server, server->router->connection, TRUE,
}
/* Get entry to the channel user list */
- silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
+ if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NOT_ON_CHANNEL);
+ goto out;
+ }
/* The client must be at least channel operator. */
if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2, id, id_len,
3, channel->ban_list,
channel->ban_list ?
- strlen(channel->ban_list) - 1 : 0);
+ strlen(channel->ban_list) : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
server->router = NULL;
server->standalone = TRUE;
}
- silc_server_free_sock_user_data(server, sock);
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
out:
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_USERS,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_users,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
silc_command_set_ident(cmd->payload, ident);
-
silc_buffer_free(tmpbuf);
silc_free(id);
- return;
+ goto out;
}
/* Check the global list as well. */
uint32 tmp_len, pklen;
SilcBuffer pk = NULL;
SilcIdType id_type;
+ SilcPublicKey public_key;
SILC_LOG_DEBUG(("Start"));
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_getkey,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
-
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
if (!client) {
/* The client is locally connected, just get the public key and
send it back. If they key does not exist then do not send it,
send just OK reply */
- if (!client->data.public_key) {
+ public_key = client->data.public_key;
+ if (!public_key) {
pkdata = NULL;
pklen = 0;
} else {
- tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
+ tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
pk = silc_buffer_alloc(4 + tmp_len);
silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
silc_buffer_format(pk,
/* Reprocess this packet after received reply from router */
silc_server_command_pending(server, SILC_COMMAND_GETKEY,
silc_command_get_ident(cmd->payload),
- silc_server_command_destructor,
silc_server_command_getkey,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
-
silc_command_set_ident(cmd->payload, old_ident);
silc_buffer_free(tmpbuf);
- return;
+ goto out;
}
if (!server_entry) {
}
/* If they key does not exist then do not send it, send just OK reply */
- if (!server_entry->data.public_key) {
+ public_key = (!server_entry->data.public_key ?
+ (server_entry == server->id_entry ? server->public_key :
+ NULL) : server_entry->data.public_key);
+ if (!public_key) {
pkdata = NULL;
pklen = 0;
} else {
- tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
- &tmp_len);
+ tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
pk = silc_buffer_alloc(4 + tmp_len);
silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
silc_buffer_format(pk,