/* Create bogus command reply with an error inside */
tmpreply =
- silc_command_reply_payload_encode_va(reply->reply_cmd,
+ silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
+ SILC_COMMAND_RESERVED,
SILC_STATUS_ERR_TIMEDOUT, 0,
reply->ident, 0);
cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
return FALSE;
}
-/******************************************************************************
+/* Server side of command WHOIS. */
- WHOIS Functions
-
-******************************************************************************/
-
-typedef struct {
- void *id;
- SilcIdType id_type;
- SilcUInt32 index;
- SilcStatus error;
-} *ResolveError;
-
-#define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
-do { \
- errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
- if (!errptr) \
- return FALSE; \
- errptr[errptr_count].id = _id; \
- errptr[errptr_count].id_type = _id_type; \
- errptr[errptr_count].index = _index; \
- errptr[errptr_count].error = _status; \
- errptr_count++; \
-} while(0)
-
-static int
-silc_server_command_whois_parse(SilcServerCommandContext cmd,
- SilcClientID ***client_id,
- SilcUInt32 *client_id_count,
- char **nickname,
- char **server_name,
- int *count,
- ResolveError *error_client,
- SilcUInt32 *error_client_count,
- SilcDList *attrs)
-{
- unsigned char *tmp;
- SilcUInt32 len;
- SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
- void *id;
- int i, k;
-
- /* If client ID is in the command it must be used instead of nickname */
- tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
- if (!tmp) {
- /* No ID, get the nickname@server string and parse it. */
- tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
- if (tmp) {
- silc_parse_userfqdn(tmp, nickname, server_name);
- } else {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_BAD_NICKNAME, 0);
- return FALSE;
- }
- } else {
- /* Command includes ID, we must use that. Take all ID's from the
- command packet */
- for (k = 0, i = 0; i < argc; i++) {
- tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
- if (!tmp)
- continue;
- id = silc_id_payload_parse_id(tmp, len, NULL);
- if (id) {
- *client_id = silc_realloc(*client_id, sizeof(**client_id) *
- (*client_id_count + 1));
- (*client_id)[k] = id;
- (*client_id_count)++;
- k++;
- } else {
- ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
- SILC_STATUS_ERR_BAD_CLIENT_ID);
- }
- }
- }
-
- /* Get the max count of reply messages allowed */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
- if (tmp)
- SILC_GET32_MSB(*count, tmp);
- else
- *count = 0;
-
- /* Get requested attributes if set */
- tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (tmp && attrs)
- *attrs = silc_attribute_payload_parse_list(tmp, len);
-
- return TRUE;
-}
-
-/* Resolve context used by both WHOIS and IDENTIFY commands */
-typedef struct {
- SilcSocketConnection sock;
- SilcUInt16 ident;
- unsigned char **res_argv;
- SilcUInt32 *res_argv_lens;
- SilcUInt32 *res_argv_types;
- SilcUInt32 res_argc;
- SilcUInt32 res_timeout;
-} *SilcServerResolveContext;
-
-static bool
-silc_server_command_whois_check(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
- SilcDList attrs)
-{
- SilcServer server = cmd->server;
- SilcClientEntry entry;
- SilcServerResolveContext resolve = NULL, r = NULL;
- SilcUInt32 resolve_count = 0;
- int i, k;
- bool no_res = TRUE;
-
- SILC_LOG_DEBUG(("Start"));
-
- for (i = 0; i < clients_count; i++) {
- entry = clients[i];
- if (!entry)
- continue;
-
- /* If requested attributes is set then we always resolve the client
- information, if not then check whether the entry is complete or not
- and decide whether we need to resolve or not. Usually attributes
- are not present so the this test is performed all the time. */
- if (!attrs) {
- 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;
- }
- }
-
- /* When requested attributes is present and local client is detached
- we cannot send the command to the client, we'll reply on behalf of
- the client instead. */
- if (attrs && SILC_IS_LOCAL(entry) && entry->mode & SILC_UMODE_DETACHED)
- continue;
-
- /* We need to resolve this entry since it is not complete */
-
- if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
- /* The entry is being resolved (and we are not the resolver) so attach
- 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_whois,
- silc_server_command_dup(cmd));
- no_res = FALSE;
- } else {
- SilcBuffer idp;
- SilcSocketConnection sock;
-
- if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
- /* We've resolved this and it still is not ready. We'll return
- and are that this will be handled again after it is resolved. */
- for (i = 0; i < resolve_count; i++) {
- for (k = 0; k < r->res_argc; k++)
- silc_free(r->res_argv[k]);
- silc_free(r->res_argv);
- silc_free(r->res_argv_lens);
- silc_free(r->res_argv_types);
- }
- silc_free(resolve);
- return FALSE;
- }
-
- /* We'll resolve this client now */
-
- sock = (SILC_IS_LOCAL(entry) ? entry->connection :
- entry->router->connection);
- if (!sock)
- continue;
-
- r = NULL;
- for (k = 0; k < resolve_count; k++) {
- if (resolve[k].sock == sock) {
- r = &resolve[k];
- break;
- }
- }
-
- if (!r) {
- resolve = silc_realloc(resolve, sizeof(*resolve) *
- (resolve_count + 1));
- r = &resolve[resolve_count];
- memset(r, 0, sizeof(*r));
- r->sock = sock;
- r->ident = ++server->cmd_ident;
- if (SILC_IS_LOCAL(entry))
- r->res_timeout = 2;
- else
- r->res_timeout = 0;
- resolve_count++;
- }
-
- r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
- (r->res_argc + 1));
- r->res_argv_lens = silc_realloc(r->res_argv_lens,
- sizeof(*r->res_argv_lens) *
- (r->res_argc + 1));
- r->res_argv_types = silc_realloc(r->res_argv_types,
- sizeof(*r->res_argv_types) *
- (r->res_argc + 1));
- idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- r->res_argv[r->res_argc] = silc_calloc(idp->len,
- sizeof(**r->res_argv));
- memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
- r->res_argv_lens[r->res_argc] = idp->len;
- r->res_argv_types[r->res_argc] = r->res_argc + 4;
- r->res_argc++;
- silc_buffer_free(idp);
-
- entry->resolve_cmd_ident = r->ident;
- entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
- entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
- }
- }
-
- /* Do the resolving */
- for (i = 0; i < resolve_count; i++) {
- SilcBuffer res_cmd;
- unsigned char *attrs_buf;
- SilcUInt32 attrs_buf_len;
-
- r = &resolve[i];
-
- /* If attributes were present put them to this resolving as well */
- if (attrs) {
- attrs_buf = silc_argument_get_arg_type(cmd->args, 3, &attrs_buf_len);
- if (attrs_buf) {
- r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
- (r->res_argc + 1));
- r->res_argv_lens = silc_realloc(r->res_argv_lens,
- sizeof(*r->res_argv_lens) *
- (r->res_argc + 1));
- r->res_argv_types = silc_realloc(r->res_argv_types,
- sizeof(*r->res_argv_types) *
- (r->res_argc + 1));
- r->res_argv[r->res_argc] = silc_memdup(attrs_buf, attrs_buf_len);
- r->res_argv_lens[r->res_argc] = attrs_buf_len;
- r->res_argv_types[r->res_argc] = 3;
- r->res_argc++;
- }
- }
-
- /* Send WHOIS command */
- res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
- r->res_argc, r->res_argv,
- r->res_argv_lens,
- r->res_argv_types,
- r->ident);
- silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
- cmd->packet->flags, res_cmd->data,
- res_cmd->len, FALSE);
-
- /* Reprocess this packet after received reply */
- silc_server_command_pending_timed(server, SILC_COMMAND_WHOIS, r->ident,
- silc_server_command_whois,
- silc_server_command_dup(cmd),
- r->res_timeout);
- cmd->pending = TRUE;
-
- silc_buffer_free(res_cmd);
- for (k = 0; k < r->res_argc; k++)
- silc_free(r->res_argv[k]);
- silc_free(r->res_argv);
- silc_free(r->res_argv_lens);
- silc_free(r->res_argv_types);
- no_res = FALSE;
- }
- silc_free(resolve);
-
- return no_res;
-}
-
-static void
-silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
- ResolveError errors,
- SilcUInt32 errors_count,
- int count, const char *nickname,
- SilcClientID **client_ids)
-{
- SilcServer server = cmd->server;
- char *tmp;
- int i, k, valid_count = clients_count;
- SilcUInt32 len;
- SilcBuffer packet, idp, channels, umode_list = NULL;
- SilcClientEntry entry;
- SilcStatus status;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- char nh[256], uh[256];
- unsigned char idle[4], mode[4];
- unsigned char *fingerprint, fempty[20];
- SilcSocketConnection hsock;
-
- if (nickname) {
- /* Process only valid clients and ignore those that are not registered.
- This is checked with nickname only because when resolved client IDs
- we check that they are registered earlier. */
- valid_count = 0;
- for (i = 0; i < clients_count; i++)
- if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
- valid_count++;
- else
- clients[i] = NULL;
-
- if (!valid_count) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 3, nickname, strlen(nickname));
- return;
- }
- }
-
- memset(fempty, 0, sizeof(fempty));
-
- /* Start processing found clients. */
- status = SILC_STATUS_OK;
- if (valid_count > 1)
- status = SILC_STATUS_LIST_START;
-
- for (i = 0, k = 0; i < clients_count; i++) {
- entry = clients[i];
- if (!entry)
- continue;
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (valid_count > 1 && k == valid_count - 1 && !errors_count)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* Send WHOIS 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));
- memset(idle, 0, sizeof(idle));
-
- strncat(nh, entry->nickname, strlen(entry->nickname));
- if (!strchr(entry->nickname, '@')) {
- strncat(nh, "@", 1);
- if (entry->servername) {
- strncat(nh, entry->servername, strlen(entry->servername));
- } else {
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
- }
- }
-
- strncat(uh, entry->username, strlen(entry->username));
- if (!strchr(entry->username, '@') && entry->connection) {
- strncat(uh, "@", 1);
- hsock = (SilcSocketConnection)entry->connection;
- len = strlen(hsock->hostname);
- strncat(uh, hsock->hostname, len);
- }
-
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
- channels = silc_server_get_client_channel_list(server, entry, FALSE,
- FALSE, &umode_list);
- else
- channels = silc_server_get_client_channel_list(server, entry, TRUE,
- TRUE, &umode_list);
-
- if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
- fingerprint = entry->data.fingerprint;
- else
- fingerprint = NULL;
-
- SILC_PUT32_MSB(entry->mode, mode);
- if (entry->connection)
- SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
-
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, 0, ident, 9,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- strlen(entry->userinfo),
- 6, channels ? channels->data : NULL,
- channels ? channels->len : 0,
- 7, mode, 4,
- 8, idle, 4,
- 9, fingerprint,
- fingerprint ? 20 : 0,
- 10, umode_list ? umode_list->data :
- NULL, umode_list ? umode_list->len :
- 0);
-
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
- 0, packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
- silc_buffer_free(idp);
- if (channels)
- silc_buffer_free(channels);
- if (umode_list) {
- silc_buffer_free(umode_list);
- umode_list = NULL;
- }
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
-
- /* Send error replies */
- if (status == SILC_STATUS_OK && errors_count > 1)
- status = SILC_STATUS_LIST_START;
-
- idp = NULL;
- for (i = 0, k = 0; i < errors_count; i++) {
- if (errors[i].id) {
- idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
- tmp = idp->data;
- len = idp->len;
- } else {
- tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
- }
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (errors_count > 1 && k == errors_count - 1)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* Send error */
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
- (status == SILC_STATUS_OK ?
- errors[i].error : status),
- (status == SILC_STATUS_OK ?
- 0 : errors[i].error),
- 2, tmp, len);
- silc_buffer_free(idp);
- idp = NULL;
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
-}
-
-static void
-silc_server_command_whois_send_router(SilcServerCommandContext cmd)
-{
- SilcServer server = cmd->server;
- SilcBuffer tmpbuf;
- SilcUInt16 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)
- SILC_PRIMARY_ROUTE(server),
- 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)
-{
- SilcServer server = cmd->server;
- char *nick = NULL, *server_name = NULL;
- int count = 0;
- SilcClientEntry *clients = NULL, entry;
- SilcClientID **client_id = NULL;
- SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
- ResolveError error_client = NULL;
- SilcDList attrs = NULL;
- int i, ret = 0;
- bool check_global = FALSE;
-
- /* Parse the whois request */
- if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
- &nick, &server_name, &count,
- &error_client, &error_client_count,
- &attrs))
- return 0;
-
- /* Send the WHOIS 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 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 &&
- !server->standalone) {
- silc_server_command_whois_send_router(cmd);
- ret = -1;
- goto out;
- }
-
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
- check_global = TRUE;
- else if (server->server_type != SILC_SERVER)
- check_global = TRUE;
-
- /* Get all clients matching that ID or nickname from local list */
- if (client_id_count) {
- /* Check all Client ID's received in the command packet */
- for (i = 0; i < client_id_count; i++) {
- entry = silc_idlist_find_client_by_id(server->local_list,
- client_id[i], TRUE, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_client_by_id(server->global_list,
- client_id[i], TRUE, NULL);
- if (entry) {
- 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;
- }
-
- ADD_ERROR(error_client, error_client_count, client_id[i],
- SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
- }
- }
- } else if (nick) {
- /* Find by nickname */
- if (!silc_idlist_get_clients_by_hash(server->local_list,
- nick, server->md5hash,
- &clients, &clients_count))
- silc_idlist_get_clients_by_nickname(server->local_list,
- nick, server_name,
- &clients, &clients_count);
- if (check_global) {
- if (!silc_idlist_get_clients_by_hash(server->global_list,
- nick, server->md5hash,
- &clients, &clients_count))
- silc_idlist_get_clients_by_nickname(server->global_list,
- nick, server_name,
- &clients, &clients_count);
- }
- }
-
- if (!clients && (client_id_count || nick)) {
- /* 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,
- SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 3, nick, strlen(nick));
- else
- silc_server_command_whois_send_reply(cmd, NULL, 0,
- error_client, error_client_count,
- 0, NULL, NULL);
- goto out;
- }
-
- /* Router always finds the client entry if it exists in the SILC network.
- However, it might be incomplete entry and does not include all the
- mandatory fields that WHOIS command reply requires. Check for these and
- make query from the server who owns the client if some fields are
- missing. */
- if (!silc_server_command_whois_check(cmd, clients, clients_count, attrs)) {
- ret = -1;
- goto out;
- }
-
- /* Send the command reply */
- silc_server_command_whois_send_reply(cmd, clients, clients_count,
- error_client, error_client_count,
- count, nick, client_id);
-
- out:
- if (client_id_count) {
- for (i = 0; i < client_id_count; i++)
- silc_free(client_id[i]);
- silc_free(client_id);
- }
- silc_free(clients);
- silc_free(error_client);
- silc_free(nick);
- silc_free(server_name);
- if (attrs)
- silc_attribute_payload_list_free(attrs);
-
- return ret;
-}
-
-/* Server side of command WHOIS. Processes user's query and sends found
- results as command replies back to the client. */
-
-SILC_SERVER_CMD_FUNC(whois)
-{
- SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
-
- silc_server_command_whois_process(cmd);
- silc_server_command_free(cmd);
-}
-
-/******************************************************************************
-
- WHOWAS Functions
-
-******************************************************************************/
-
-static int
-silc_server_command_whowas_parse(SilcServerCommandContext cmd,
- char **nickname,
- char **server_name,
- int *count)
-{
- unsigned char *tmp;
- SilcUInt32 len;
-
- tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
- 0);
- return FALSE;
- }
-
- /* Get the nickname@server string and parse it. */
- silc_parse_userfqdn(tmp, nickname, server_name);
-
- /* Get the max count of reply messages allowed */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
- if (tmp)
- SILC_GET32_MSB(*count, tmp);
- else
- *count = 0;
-
- return TRUE;
-}
-
-static char
-silc_server_command_whowas_check(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count)
-{
- SilcServer server = cmd->server;
- int i;
- SilcClientEntry entry;
-
- for (i = 0; i < clients_count; i++) {
- entry = clients[i];
-
- if (!entry->nickname || !entry->username) {
- SilcBuffer tmpbuf;
- SilcUInt16 old_ident;
-
- if (!entry->router)
- continue;
-
- 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 WHOWAS command */
- silc_server_packet_send(server, entry->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
-
- /* Reprocess this packet after received reply */
- silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
- silc_command_get_ident(cmd->payload),
- silc_server_command_whowas,
- silc_server_command_dup(cmd));
- cmd->pending = TRUE;
- silc_command_set_ident(cmd->payload, old_ident);
-
- silc_buffer_free(tmpbuf);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static void
-silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count)
-{
- SilcServer server = cmd->server;
- char *tmp;
- int i, k, count = 0, len;
- SilcBuffer packet, idp;
- SilcClientEntry entry = NULL;
- SilcStatus status;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- char nh[256], uh[256];
- int valid_count;
-
- status = SILC_STATUS_OK;
-
- /* Process only entries that are not registered anymore. */
- valid_count = 0;
- for (i = 0; i < clients_count; i++) {
- if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
- clients[i] = NULL;
- else
- valid_count++;
- }
-
- if (!valid_count) {
- /* No valid entries found at all, just send error */
- tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
- SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 3, tmp, tmp ? strlen(tmp) : 0);
- return;
- }
-
- if (valid_count > 1)
- status = SILC_STATUS_LIST_START;
-
- for (i = 0, k = 0; i < clients_count; i++) {
- entry = clients[i];
- if (!entry)
- continue;
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (valid_count > 1 && k == valid_count - 1)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* 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));
-
- strncat(nh, entry->nickname, strlen(entry->nickname));
- if (!strchr(entry->nickname, '@')) {
- strncat(nh, "@", 1);
- if (entry->servername) {
- strncat(nh, entry->servername, strlen(entry->servername));
- } else {
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
- }
- }
-
- strncat(uh, entry->username, strlen(entry->username));
- if (!strchr(entry->username, '@')) {
- strncat(uh, "@", 1);
- strcat(uh, "*private*");
- }
-
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
- status, 0, ident, 4,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- entry->userinfo ?
- strlen(entry->userinfo) : 0);
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
- 0, packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
- silc_buffer_free(idp);
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
-}
-
-static int
-silc_server_command_whowas_process(SilcServerCommandContext cmd)
-{
- SilcServer server = cmd->server;
- char *nick = NULL, *server_name = NULL;
- int count = 0;
- SilcClientEntry *clients = NULL;
- SilcUInt32 clients_count = 0;
- int ret = 0;
- bool check_global = FALSE;
-
- /* Protocol dictates that we must always send the received WHOWAS request
- to our router if we are normal server, so let's do it now unless we
- are standalone. We will not send any replies to the client until we
- have received reply from the router. */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- server->server_type == SILC_SERVER && !cmd->pending &&
- !server->standalone) {
- SilcBuffer tmpbuf;
- SilcUInt16 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 WHOWAS command to our router */
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- 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_WHOWAS,
- silc_command_get_ident(cmd->payload),
- silc_server_command_whowas,
- silc_server_command_dup(cmd));
- cmd->pending = TRUE;
- silc_command_set_ident(cmd->payload, old_ident);
-
- silc_buffer_free(tmpbuf);
- ret = -1;
- goto out;
- }
-
- /* We are ready to process the command request. Let's search for the
- requested client and send reply to the requesting client. */
-
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
- check_global = TRUE;
- else if (server->server_type != SILC_SERVER)
- check_global = TRUE;
-
- /* Parse the whowas request */
- if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
- return 0;
-
- /* Get all clients matching that nickname from local list */
- if (!silc_idlist_get_clients_by_nickname(server->local_list,
- nick, server_name,
- &clients, &clients_count))
- silc_idlist_get_clients_by_hash(server->local_list,
- nick, server->md5hash,
- &clients, &clients_count);
-
- /* Check global list as well */
- if (check_global) {
- if (!silc_idlist_get_clients_by_nickname(server->global_list,
- nick, server_name,
- &clients, &clients_count))
- silc_idlist_get_clients_by_hash(server->global_list,
- nick, server->md5hash,
- &clients, &clients_count);
- }
-
- if (!clients) {
- /* Such a client really does not exist in the SILC network. */
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
- SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 3, nick, strlen(nick));
- goto out;
- }
-
- if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
- ret = -1;
- goto out;
- }
-
- /* Send the command reply to the client */
- silc_server_command_whowas_send_reply(cmd, clients, clients_count);
-
- out:
- silc_free(clients);
- silc_free(nick);
- silc_free(server_name);
- return ret;
-}
-
-/* Server side of command WHOWAS. */
-
-SILC_SERVER_CMD_FUNC(whowas)
-{
- SilcServerCommandContext cmd = (SilcServerCommandContext)context;
- int ret = 0;
-
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
-
- ret = silc_server_command_whowas_process(cmd);
- silc_server_command_free(cmd);
-}
-
-/******************************************************************************
-
- IDENTIFY Functions
-
-******************************************************************************/
-
-static void
-silc_server_command_identify_send_router(SilcServerCommandContext cmd)
-{
- SilcServer server = cmd->server;
- SilcBuffer tmpbuf;
- SilcUInt16 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)
- SILC_PRIMARY_ROUTE(server),
- 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,
- SilcUInt32 *clients_count,
- SilcServerEntry **servers,
- SilcUInt32 *servers_count,
- SilcChannelEntry **channels,
- SilcUInt32 *channels_count,
- SilcUInt32 *count,
- ResolveError *error_id,
- SilcUInt32 *error_id_count)
-{
- SilcServer server = cmd->server;
- unsigned char *tmp;
- SilcUInt32 len;
- SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
- SilcIDPayload idp;
- bool check_global = FALSE;
- void *entry;
- int i;
-
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
- check_global = TRUE;
- else if (server->server_type != SILC_SERVER)
- check_global = TRUE;
-
- /* If ID Payload is in the command it must be used instead of names */
- tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
- if (!tmp) {
- /* No ID, get the names. */
-
- /* 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);
- if (tmp) {
- char *nick = NULL;
- char *nick_server = NULL;
-
- silc_parse_userfqdn(tmp, &nick, &nick_server);
-
- if (!silc_idlist_get_clients_by_hash(server->local_list,
- nick, server->md5hash,
- clients, clients_count))
- silc_idlist_get_clients_by_nickname(server->local_list,
- nick, nick_server,
- clients, clients_count);
- if (check_global) {
- if (!silc_idlist_get_clients_by_hash(server->global_list,
- nick, server->md5hash,
- clients, clients_count))
- silc_idlist_get_clients_by_nickname(server->global_list,
- nick, nick_server,
- clients, clients_count);
- }
-
- silc_free(nick);
- 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, 0,
- 3, tmp, strlen(tmp));
- return 0;
- }
- }
-
- /* Try to get server name */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
- if (tmp) {
- entry = silc_idlist_find_server_by_name(server->local_list,
- tmp, TRUE, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_server_by_name(server->global_list,
- tmp, TRUE, NULL);
- if (entry) {
- *servers = silc_realloc(*servers, sizeof(**servers) *
- (*servers_count + 1));
- (*servers)[(*servers_count)++] = entry;
- }
-
- 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,
- 0, 3, tmp, strlen(tmp));
- return 0;
- }
- }
-
- /* Try to get channel name */
- tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
- if (tmp) {
- entry = silc_idlist_find_channel_by_name(server->local_list,
- tmp, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_channel_by_name(server->global_list,
- tmp, NULL);
- if (entry) {
- *channels = silc_realloc(*channels, sizeof(**channels) *
- (*channels_count + 1));
- (*channels)[(*channels_count)++] = entry;
- }
-
- 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,
- 0, 3, tmp, strlen(tmp));
- return 0;
- }
- }
-
- if (!(*clients) && !(*servers) && !(*channels)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
- 0);
- return 0;
- }
- } else {
- /* Command includes ID, we must use that. Also check whether the command
- has more than one ID set - take them all. */
-
- /* Take all ID's from the command packet */
- for (i = 0; i < argc; i++) {
- void *id;
-
- tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
- if (!tmp)
- continue;
-
- idp = silc_id_payload_parse(tmp, len);
- if (!idp)
- ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-
- id = silc_id_payload_get_id(idp);
- switch (silc_id_payload_get_type(idp)) {
-
- case SILC_ID_CLIENT:
- entry = silc_idlist_find_client_by_id(server->local_list,
- id, TRUE, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_client_by_id(server->global_list,
- id, TRUE, NULL);
- if (entry) {
- *clients = silc_realloc(*clients, sizeof(**clients) *
- (*clients_count + 1));
- (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
- } else {
- /* 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);
- silc_free(*error_id);
- return -1;
- }
-
- ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
- }
-
- break;
-
- case SILC_ID_SERVER:
- entry = silc_idlist_find_server_by_id(server->local_list,
- id, TRUE, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_server_by_id(server->global_list,
- id, TRUE, NULL);
- if (entry) {
- *servers = silc_realloc(*servers, sizeof(**servers) *
- (*servers_count + 1));
- (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
- } else {
- /* 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);
- silc_free(*error_id);
- return -1;
- }
-
- ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
- SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
- }
- break;
-
- case SILC_ID_CHANNEL:
- entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
- if (!entry && check_global)
- entry = silc_idlist_find_channel_by_id(server->global_list, id,
- NULL);
- if (entry) {
- *channels = silc_realloc(*channels, sizeof(**channels) *
- (*channels_count + 1));
- (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
- } else {
- /* 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);
- silc_free(*error_id);
- return -1;
- }
-
- ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
- }
- break;
- }
-
- silc_id_payload_free(idp);
- silc_free(id);
- }
- }
-
- /* Get the max count of reply messages allowed */
- tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
- if (tmp)
- SILC_GET32_MSB(*count, tmp);
- else
- *count = 0;
-
- return 1;
-}
-
-/* Checks that all mandatory fields in client entry are present. If not
- then send WHOIS request to the server who owns the client. We use
- WHOIS because we want to get as much information as possible at once. */
-
-static bool
-silc_server_command_identify_check_client(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count)
-{
- SilcServer server = cmd->server;
- SilcClientEntry entry;
- SilcServerResolveContext resolve = NULL, r = NULL;
- SilcUInt32 resolve_count = 0;
- int i, k;
- bool no_res = TRUE;
-
- for (i = 0; i < clients_count; i++) {
- entry = clients[i];
- 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) {
- /* The entry is being resolved (and we are not the resolver) so attach
- 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_identify,
- silc_server_command_dup(cmd));
- no_res = FALSE;
- } else {
- if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
- /* We've resolved this and it still is not ready. We'll return
- and are that this will be handled again after it is resolved. */
- for (i = 0; i < resolve_count; i++) {
- for (k = 0; k < r->res_argc; k++)
- silc_free(r->res_argv[k]);
- silc_free(r->res_argv);
- silc_free(r->res_argv_lens);
- silc_free(r->res_argv_types);
- }
- silc_free(resolve);
- return FALSE;
- } else {
- /* We'll resolve this client */
- SilcBuffer idp;
-
- r = NULL;
- for (k = 0; k < resolve_count; k++) {
- if (resolve[k].sock == entry->router->connection) {
- r = &resolve[k];
- break;
- }
- }
-
- if (!r) {
- resolve = silc_realloc(resolve, sizeof(*resolve) *
- (resolve_count + 1));
- r = &resolve[resolve_count];
- memset(r, 0, sizeof(*r));
- r->sock = entry->router->connection;
- r->ident = ++server->cmd_ident;
- resolve_count++;
- }
-
- r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
- (r->res_argc + 1));
- r->res_argv_lens = silc_realloc(r->res_argv_lens,
- sizeof(*r->res_argv_lens) *
- (r->res_argc + 1));
- r->res_argv_types = silc_realloc(r->res_argv_types,
- sizeof(*r->res_argv_types) *
- (r->res_argc + 1));
- idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- r->res_argv[r->res_argc] = silc_calloc(idp->len,
- sizeof(**r->res_argv));
- memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
- r->res_argv_lens[r->res_argc] = idp->len;
- r->res_argv_types[r->res_argc] = r->res_argc + 4;
- r->res_argc++;
- silc_buffer_free(idp);
-
- entry->resolve_cmd_ident = r->ident;
- entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
- entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
- }
- }
- }
-
- /* Do the resolving */
- for (i = 0; i < resolve_count; i++) {
- SilcBuffer res_cmd;
-
- r = &resolve[i];
-
- /* Send WHOIS request. We send WHOIS since we're doing the requesting
- now anyway so make it a good one. */
- res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
- r->res_argc, r->res_argv,
- r->res_argv_lens,
- r->res_argv_types,
- r->ident);
- silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
- cmd->packet->flags, res_cmd->data,
- res_cmd->len, FALSE);
-
- /* Reprocess this packet after received reply */
- silc_server_command_pending(server, SILC_COMMAND_WHOIS,
- r->ident,
- silc_server_command_identify,
- silc_server_command_dup(cmd));
- cmd->pending = TRUE;
-
- silc_buffer_free(res_cmd);
- for (k = 0; k < r->res_argc; k++)
- silc_free(r->res_argv[k]);
- silc_free(r->res_argv);
- silc_free(r->res_argv_lens);
- silc_free(r->res_argv_types);
- no_res = FALSE;
- }
- silc_free(resolve);
-
- return no_res;
-}
-
-static void
-silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
- SilcServerEntry *servers,
- SilcUInt32 servers_count,
- SilcChannelEntry *channels,
- SilcUInt32 channels_count,
- ResolveError errors,
- SilcUInt32 errors_count,
- int count)
-{
- SilcServer server = cmd->server;
- int i, k, valid_count;
- SilcUInt32 len;
- SilcBuffer packet, idp;
- SilcStatus status;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- char nh[256], uh[256];
- SilcSocketConnection hsock;
- unsigned char *tmp;
-
- status = SILC_STATUS_OK;
-
- if (clients) {
- SilcClientEntry entry;
- valid_count = clients_count;
-
- if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
- /* Process only valid clients and ignore those that are not registered.
- This is checked with nickname only because when resolved client IDs
- we check that they are registered earlier. */
- valid_count = 0;
- for (i = 0; i < clients_count; i++) {
- if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
- valid_count++;
- else
- clients[i] = NULL;
- }
-
- if (!valid_count) {
- /* No valid entries found at all, just send error */
- tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 3, tmp, tmp ? strlen(tmp) : 0);
- return;
- }
- }
-
- /* 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)
- continue;
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (valid_count > 1 && k == valid_count - 1
- && !servers_count && !channels_count && !errors_count)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* 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);
- if (entry->servername) {
- strncat(nh, entry->servername, strlen(entry->servername));
- } else {
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
- }
- }
-
- if (!entry->username) {
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- status, 0, ident, 2,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh));
- } else {
- strncat(uh, entry->username, strlen(entry->username));
- if (!strchr(entry->username, '@') && entry->connection) {
- strncat(uh, "@", 1);
- hsock = (SilcSocketConnection)entry->connection;
- len = strlen(hsock->hostname);
- strncat(uh, hsock->hostname, len);
- }
-
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- status, 0, ident, 3,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh));
- }
-
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
- 0, packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
- silc_buffer_free(idp);
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
- }
-
- if (servers) {
- SilcServerEntry entry;
-
- if (status == SILC_STATUS_OK && servers_count > 1)
- status = SILC_STATUS_LIST_START;
-
- for (i = 0, k = 0; i < servers_count; i++) {
- entry = servers[i];
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
- !errors_count)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* Send IDENTIFY reply */
- idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- status, 0, ident, 2,
- 2, idp->data, idp->len,
- 3, entry->server_name,
- entry->server_name ?
- strlen(entry->server_name) : 0);
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
- 0, packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
- silc_buffer_free(idp);
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
- }
-
- if (channels) {
- SilcChannelEntry entry;
-
- if (status == SILC_STATUS_OK && channels_count > 1)
- status = SILC_STATUS_LIST_START;
-
- for (i = 0, k = 0; i < channels_count; i++) {
- entry = channels[i];
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (channels_count > 1 && k == channels_count - 1 && !errors_count)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* Send IDENTIFY reply */
- idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- status, 0, ident, 2,
- 2, idp->data, idp->len,
- 3, entry->channel_name,
- entry->channel_name ?
- strlen(entry->channel_name): 0);
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
- 0, packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
- silc_buffer_free(idp);
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
- }
-
- /* Send error replies */
- if (errors) {
- if (status == SILC_STATUS_OK && errors_count > 1)
- status = SILC_STATUS_LIST_START;
-
- idp = NULL;
- for (i = 0, k = 0; i < errors_count; i++) {
- if (errors[i].id) {
- idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
- tmp = idp->data;
- len = idp->len;
- } else {
- tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
- }
-
- if (k >= 1)
- status = SILC_STATUS_LIST_ITEM;
- if (errors_count > 1 && k == errors_count - 1)
- status = SILC_STATUS_LIST_END;
- if (count && k - 1 == count)
- status = SILC_STATUS_LIST_END;
-
- /* Send error */
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- (status == SILC_STATUS_OK ?
- errors[i].error : status),
- (status == SILC_STATUS_OK ?
- 0 : errors[i].error),
- 2, tmp, len);
- silc_buffer_free(idp);
- idp = NULL;
-
- if (status == SILC_STATUS_LIST_END)
- break;
- k++;
- }
- }
-}
-
-static int
-silc_server_command_identify_process(SilcServerCommandContext cmd)
+SILC_SERVER_CMD_FUNC(whois)
{
- SilcUInt32 count = 0;
- int ret = 0;
- SilcClientEntry *clients = NULL;
- SilcServerEntry *servers = NULL;
- SilcChannelEntry *channels = NULL;
- SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
- SilcUInt32 errors_count = 0;
- ResolveError errors = NULL;
-
- /* Parse the IDENTIFY request */
- ret = silc_server_command_identify_parse(cmd,
- &clients, &clients_count,
- &servers, &servers_count,
- &channels, &channels_count,
- &count, &errors, &errors_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. */
- if (!silc_server_command_identify_check_client(cmd, clients,
- clients_count)) {
- ret = -1;
- goto out;
- }
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
+ silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
+ silc_server_command_free(cmd);
+}
- /* Send the command reply to the client */
- silc_server_command_identify_send_reply(cmd,
- clients, clients_count,
- servers, servers_count,
- channels, channels_count,
- errors, errors_count,
- count);
+/* Server side of command WHOWAS. */
- out:
- silc_free(clients);
- silc_free(servers);
- silc_free(channels);
- silc_free(errors);
- return ret;
+SILC_SERVER_CMD_FUNC(whowas)
+{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
+ silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
+ silc_server_command_free(cmd);
}
+/* Server side of command IDENTIFY. */
+
SILC_SERVER_CMD_FUNC(identify)
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
- int ret = 0;
-
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
-
- ret = silc_server_command_identify_process(cmd);
+ silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
silc_server_command_free(cmd);
}
/* Check nickname */
nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
+ if (!nick) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
+ SILC_STATUS_ERR_BAD_NICKNAME, 0);
+ goto out;
+ }
if (nick_len > 128)
nick[128] = '\0';
if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
/* If we are normal server, send the command to router, since we
want to know all channels in the network. */
- if (!cmd->pending && server->server_type == SILC_SERVER &&
+ if (!cmd->pending && server->server_type != SILC_ROUTER &&
!server->standalone) {
SilcBuffer tmpbuf;
SilcUInt16 old_ident;
SilcChannelEntry channel;
SilcChannelID *channel_id = NULL;
SilcIDListData idata;
- SilcBuffer idp, idp2, packet;
- unsigned char *tmp, *add, *del;
- SilcUInt32 len;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ SilcArgumentPayload args;
+ SilcHashTableList htl;
+ SilcBuffer packet, list, tmp2;
+ unsigned char *tmp;
+ SilcUInt32 len, type;
+ SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
/* Get destination client ID */
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, NULL);
/* Get the client entry */
dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
if (!dest) {
- if (server->server_type != SILC_SERVER || !resolve) {
+ if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
silc_server_command_send_status_reply(
cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
goto out;
}
- memset(invite, 0, sizeof(invite));
- strncat(invite, dest->nickname, strlen(dest->nickname));
- strncat(invite, "!", 1);
- strncat(invite, dest->username, strlen(dest->username));
- if (!strchr(dest->username, '@')) {
- strncat(invite, "@", 1);
- strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
- }
+ /* Add the client to the invite list */
- len = strlen(invite);
+ /* Allocate hash table for invite list if it doesn't exist yet */
if (!channel->invite_list)
- channel->invite_list = silc_calloc(len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (len +
- strlen(channel->invite_list) + 2));
- strncat(channel->invite_list, invite, len);
- strncat(channel->invite_list, ",", 1);
+ channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check if the ID is in the list already */
+ silc_hash_table_list(channel->invite_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) {
+ list = silc_buffer_alloc_size(len);
+ silc_buffer_put(list, tmp, len);
+ silc_hash_table_add(channel->invite_list, (void *)3, list);
+ }
if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
/* Send notify to the client that is invited to the channel */
+ SilcBuffer idp, idp2;
idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
}
}
- /* Add the client to the invite list of the channel */
- add = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (add) {
- if (!channel->invite_list)
- channel->invite_list = silc_calloc(len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (len +
- strlen(channel->invite_list) + 2));
- if (add[len - 1] == ',')
- add[len - 1] = '\0';
-
- strncat(channel->invite_list, add, len);
- strncat(channel->invite_list, ",", 1);
- }
-
- /* Get the invite to be removed and remove it from the list */
- del = silc_argument_get_arg_type(cmd->args, 4, &len);
- if (del && channel->invite_list) {
- char *start, *end, *n;
+ /* Get the invite information */
+ tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
+ if (tmp) {
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(argc, tmp);
+ args = silc_argument_payload_parse(tmp + 2, len - 2, argc);
+ if (!args) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+ 0);
+ goto out;
+ }
- if (!strncmp(channel->invite_list, del,
- strlen(channel->invite_list) - 1)) {
- silc_free(channel->invite_list);
- channel->invite_list = NULL;
- } else {
- start = strstr(channel->invite_list, del);
- if (start && strlen(start) >= len) {
- end = start + len;
- n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
- strncat(n, channel->invite_list, start - channel->invite_list);
- strncat(n, end + 1, ((channel->invite_list +
- strlen(channel->invite_list)) - end) - 1);
- silc_free(channel->invite_list);
- channel->invite_list = n;
+ /* Get the type of action */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp && len == 1) {
+ if (tmp[0] == 0x00) {
+ /* Allocate hash table for invite list if it doesn't exist yet */
+ if (!channel->invite_list)
+ channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check for resource limit */
+ if (silc_hash_table_count(channel->invite_list) > 64) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_RESOURCE_LIMIT,
+ 0);
+ goto out;
+ }
}
+
+ /* Now add or delete the information. */
+ silc_server_inviteban_process(server, channel->invite_list,
+ (SilcUInt8)tmp[0], args);
+ }
+ silc_argument_payload_free(args);
+ }
+
+ /* Encode invite list */
+ list = NULL;
+ if (channel->invite_list) {
+ list = silc_buffer_alloc_size(2);
+ silc_buffer_format(list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->invite_list)),
+ SILC_STR_END);
+ silc_hash_table_list(channel->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 1)
+ list = silc_argument_payload_encode_one(list, (char *)tmp2,
+ strlen((char *)tmp2), type);
+ else
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
}
+ silc_hash_table_list_reset(&htl);
}
/* Send notify to the primary router */
- silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
- SILC_BROADCAST(server), channel,
- sender->id, add, del);
+ silc_server_send_notify_invite(
+ server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server), channel, sender->id,
+ silc_argument_get_arg_type(cmd->args, 3, NULL),
+ list);
/* Send command reply */
tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
-
- if (add || del)
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
- SILC_STATUS_OK, 0, ident, 2,
- 2, tmp, len,
- 3, channel->invite_list,
- channel->invite_list ?
- strlen(channel->invite_list) : 0);
- else
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
- SILC_STATUS_OK, 0, ident, 1,
- 2, tmp, len);
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
+ SILC_STATUS_OK, 0, ident, 2,
+ 2, tmp, len,
+ 3, list ? list->data : NULL,
+ list ? list->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
+ silc_buffer_free(list);
out:
silc_free(dest_id);
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
SilcClientEntry remote_client;
- SilcClientID *client_id;
- unsigned char *tmp, *comment;
- SilcUInt32 tmp_len, tmp_len2;
- bool local;
+ SilcClientID *client_id = NULL;
+ unsigned char *tmp, *comment, *auth;
+ SilcUInt32 tmp_len, tmp_len2, auth_len;
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
goto out;
- /* KILL command works only on router */
- if (server->server_type != SILC_ROUTER) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
- SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
- goto out;
- }
+ /* Get authentication payload if present */
+ auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
- /* Check whether client has the permissions. */
- if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
- SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
- goto out;
+ if (!auth) {
+ /* Router operator killing */
+
+ /* KILL command works only on router */
+ if (server->server_type != SILC_ROUTER) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
+ goto out;
+ }
+
+ /* Check whether client has the permissions. */
+ if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
+ goto out;
+ }
}
/* Get the client ID */
/* 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,
/* Get comment */
comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
- if (tmp_len2 > 128)
+ if (comment && tmp_len2 > 128) {
tmp_len2 = 128;
+ comment[127] = '\0';
+ }
- /* Send reply to the sender */
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
- SILC_STATUS_OK, 0);
+ /* If authentication data is provided then verify that killing is
+ actually allowed */
+ if (auth && auth_len) {
+ SilcSocketConnection sock;
- /* 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);
+ if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ 0);
+ goto out;
+ }
+
+ /* Verify the signature */
+ if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
+ remote_client->data.public_key, 0,
+ server->sha1hash, remote_client->id,
+ SILC_ID_CLIENT)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_AUTH_FAILED,
+ 0);
+ goto out;
+ }
+
+ /* Send reply to the sender */
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_OK, 0);
+
+ /* Do normal signoff for the destination client */
+ sock = remote_client->connection;
+ silc_server_free_client_data(server, NULL, remote_client, TRUE,
+ comment ? comment :
+ (unsigned char *)"Killed");
+ if (sock)
+ silc_server_close_connection(server, sock);
+ } else {
+ /* Router operator killing */
+
+ /* Send reply to the sender */
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_OK, 0);
+
+ /* 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);
- /* Now do the killing */
- silc_server_kill_client(server, remote_client, comment, client->id,
- SILC_ID_CLIENT);
+ /* Now do the killing */
+ silc_server_kill_client(server, remote_client, comment, client->id,
+ SILC_ID_CLIENT);
+ }
out:
+ silc_free(client_id);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- SilcServerID *id;
- SilcUInt32 len;
+ SilcUInt32 tmp_len;
unsigned char *tmp;
+ SilcServerID *server_id = NULL;
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
/* Get Server ID */
- tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
if (!tmp) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_ERR_NO_SERVER_ID, 0);
goto out;
}
- id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
- if (!id)
+ server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+ if (!server_id)
goto out;
- if (SILC_ID_SERVER_COMPARE(id, server->id)) {
+ if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
/* Send our reply */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_OK, 0);
goto out;
}
- silc_free(id);
-
out:
+ silc_free(server_id);
silc_server_command_free(cmd);
}
/* Get Server ID */
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_ERR_NO_SERVER_ID, 0);
goto out;
}
/* The ID must be ours */
if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
silc_free(server_id);
goto out;
unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
SilcClientEntry client;
SilcChannelClientEntry chl;
- SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
+ SilcBuffer reply, chidp, clidp, keyp = NULL;
+ SilcBuffer user_list, mode_list, invite_list, ban_list;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
char check[512], check2[512];
bool founder = FALSE;
bool resolve;
- unsigned char *fkey = NULL;
- SilcUInt32 fkey_len = 0;
+ SilcBuffer fkey = NULL;
+ const char *cipher;
SILC_LOG_DEBUG(("Joining client to channel"));
client = silc_server_query_client(server, client_id, FALSE,
&resolve);
if (!client) {
- if (cmd->pending)
- goto out;
-
- if (!resolve) {
+ if (!resolve || cmd->pending) {
silc_server_command_send_status_reply(
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
goto out;
}
+ if (auth && auth_len && !client->data.public_key) {
+ if (cmd->pending == 2)
+ goto out;
+
+ /* We must retrieve the detached client's public key by sending
+ GETKEY command. Reprocess this packet after receiving the key */
+ clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+ silc_server_send_command(server, cmd->sock,
+ SILC_COMMAND_GETKEY, ++server->cmd_ident,
+ 1, 1, clidp->data, clidp->len);
+ silc_buffer_free(clidp);
+ silc_server_command_pending(server, SILC_COMMAND_GETKEY,
+ server->cmd_ident,
+ silc_server_command_join,
+ silc_server_command_dup(cmd));
+ cmd->pending = 2;
+ goto out;
+ }
+
cmd->pending = FALSE;
}
if (!umode) {
memset(check, 0, sizeof(check));
memset(check2, 0, sizeof(check2));
- strncat(check, client->nickname, strlen(client->nickname));
- strncat(check, "!", 1);
- strncat(check, client->username, strlen(client->username));
+ silc_strncat(check, sizeof(check),
+ client->nickname, strlen(client->nickname));
+ silc_strncat(check, sizeof(check), "!", 1);
+ silc_strncat(check, sizeof(check),
+ client->username, strlen(client->username));
if (!strchr(client->username, '@')) {
- strncat(check, "@", 1);
- strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
+ silc_strncat(check, sizeof(check), "@", 1);
+ silc_strncat(check, sizeof(check),
+ cmd->sock->hostname, strlen(cmd->sock->hostname));
}
- strncat(check2, client->nickname, strlen(client->nickname));
+ silc_strncat(check2, sizeof(check2),
+ client->nickname, strlen(client->nickname));
if (!strchr(client->nickname, '@')) {
- strncat(check2, "@", 1);
- strncat(check2, server->server_name, strlen(server->server_name));
+ silc_strncat(check2, sizeof(check2), "@", 1);
+ silc_strncat(check2, sizeof(check2),
+ server->server_name, strlen(server->server_name));
}
- strncat(check2, "!", 1);
- strncat(check2, client->username, strlen(client->username));
+ silc_strncat(check2, sizeof(check2), "!", 1);
+ silc_strncat(check2, sizeof(check2),
+ client->username, strlen(client->username));
if (!strchr(client->username, '@')) {
- strncat(check2, "@", 1);
- strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
+ silc_strncat(check2, sizeof(check2), "@", 1);
+ silc_strncat(check2, sizeof(check2),
+ cmd->sock->hostname, strlen(cmd->sock->hostname));
}
/* Check invite list if channel is invite-only channel */
if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
if (!channel->invite_list ||
- (!silc_string_match(channel->invite_list, check) &&
- !silc_string_match(channel->invite_list, check2))) {
+ (!silc_server_inviteban_match(server, channel->invite_list,
+ 3, client->id) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 2, client->data.public_key) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check2))) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NOT_INVITED, 0);
goto out;
username and/or hostname is in the ban list the access to the
channel is denied. */
if (channel->ban_list) {
- if (silc_string_match(channel->ban_list, check) ||
- silc_string_match(channel->ban_list, check2)) {
+ if (silc_server_inviteban_match(server, channel->invite_list,
+ 3, client->id) ||
+ silc_server_inviteban_match(server, channel->invite_list,
+ 2, client->data.public_key) ||
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check) ||
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check2)) {
silc_server_command_send_status_reply(
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ cipher = silc_cipher_get_name(channel->channel_key);
keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
SILC_ID_CHANNEL),
tmp,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->cipher->name,
+ strlen(cipher), cipher,
channel->key_len / 8, channel->key);
silc_free(tmp);
}
if (channel->founder_key)
- fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+ fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+
+ /* Encode invite list */
+ invite_list = NULL;
+ if (channel->invite_list) {
+ SilcHashTableList htl;
+
+ invite_list = silc_buffer_alloc_size(2);
+ silc_buffer_format(invite_list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->invite_list)),
+ SILC_STR_END);
+
+ silc_hash_table_list(channel->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
+ if (tmp_len == 1)
+ invite_list = silc_argument_payload_encode_one(invite_list,
+ (char *)reply,
+ strlen((char *)reply),
+ tmp_len);
+ else
+ invite_list = silc_argument_payload_encode_one(invite_list,
+ reply->data,
+ reply->len, tmp_len);
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ /* Encode ban list */
+ ban_list = NULL;
+ if (channel->ban_list) {
+ SilcHashTableList htl;
+
+ ban_list = silc_buffer_alloc_size(2);
+ silc_buffer_format(ban_list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->ban_list)),
+ SILC_STR_END);
+
+ silc_hash_table_list(channel->ban_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
+ if (tmp_len == 1)
+ ban_list = silc_argument_payload_encode_one(ban_list,
+ (char *)reply,
+ strlen((char *)reply),
+ tmp_len);
+ else
+ ban_list = silc_argument_payload_encode_one(ban_list,
+ reply->data,
+ reply->len, tmp_len);
+ }
+ silc_hash_table_list_reset(&htl);
+ }
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
6, tmp2, 4,
7, keyp ? keyp->data : NULL,
keyp ? keyp->len : 0,
- 8, channel->ban_list,
- channel->ban_list ?
- strlen(channel->ban_list) : 0,
- 9, channel->invite_list,
- channel->invite_list ?
- strlen(channel->invite_list) : 0,
+ 8, ban_list ? ban_list->data : NULL,
+ ban_list ? ban_list->len : 0,
+ 9, invite_list ? invite_list->data :
+ NULL,
+ invite_list ? invite_list->len : 0,
10, channel->topic,
channel->topic ?
strlen(channel->topic) : 0,
13, user_list->data, user_list->len,
14, mode_list->data,
mode_list->len,
- 15, fkey, fkey_len);
+ 15, fkey ? fkey->data : NULL,
+ fkey ? fkey->len : 0);
/* Send command reply */
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
clidp->data, clidp->len,
mode, 4, clidp->data, clidp->len,
- fkey, fkey_len);
+ fkey ? fkey->data : NULL,
+ fkey ? fkey->len : 0);
}
}
silc_buffer_free(keyp);
silc_buffer_free(user_list);
silc_buffer_free(mode_list);
- silc_free(fkey);
+ silc_buffer_free(fkey);
+ silc_buffer_free(invite_list);
+ silc_buffer_free(ban_list);
out:
silc_free(passphrase);
}
if (!entry) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
goto out;
}
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
bool set_mask = FALSE;
SilcPublicKey founder_key = NULL;
- unsigned char *fkey = NULL;
- SilcUInt32 fkey_len = 0;
+ SilcBuffer fkey = NULL;
if (!client) {
silc_server_command_free(cmd);
return;
}
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 8);
/* Get Channel ID */
tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
silc_server_send_channel_key(server, NULL, channel,
server->server_type == SILC_ROUTER ?
FALSE : !server->standalone);
-
- cipher = channel->channel_key->cipher->name;
+
+ cipher = (char *)silc_cipher_get_name(channel->channel_key);
hmac = (char *)silc_hmac_get_name(channel->hmac);
}
}
if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
- if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
- /* Set the founder authentication */
- tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
- if (!tmp) {
- silc_server_command_send_status_reply(
- cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
- goto out;
- }
-
- /* Verify the payload before setting the mode */
- if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
- idata->public_key, 0, server->sha1hash,
- client->id, SILC_ID_CLIENT)) {
+ /* Check if the founder public key was received */
+ founder_key = idata->public_key;
+ tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
+ if (tmp) {
+ if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_AUTH_FAILED,
0);
goto out;
}
+ }
- /* Save the public key */
- channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
- if (!channel->founder_key) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_AUTH_FAILED,
- 0);
- goto out;
- }
+ /* Set the founder authentication */
+ tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
+ if (!tmp) {
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
+ goto out;
+ }
- founder_key = channel->founder_key;
- fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
- if (!fkey) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_AUTH_FAILED,
- 0);
- silc_pkcs_public_key_free(channel->founder_key);
- channel->founder_key = NULL;
- goto out;
- }
+ /* Verify the payload before setting the mode */
+ if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
+ founder_key, 0, server->sha1hash,
+ client->id, SILC_ID_CLIENT)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_AUTH_FAILED,
+ 0);
+ goto out;
+ }
+
+ /* Save the public key */
+ if (channel->founder_key)
+ silc_pkcs_public_key_free(channel->founder_key);
+ if (silc_argument_get_arg_type(cmd->args, 8, NULL))
+ channel->founder_key = founder_key;
+ else
+ channel->founder_key = silc_pkcs_public_key_copy(founder_key);
+ if (!channel->founder_key) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_AUTH_FAILED,
+ 0);
+ goto out;
+ }
+
+ fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ if (!fkey) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_AUTH_FAILED,
+ 0);
+ silc_pkcs_public_key_free(channel->founder_key);
+ channel->founder_key = NULL;
+ goto out;
}
}
} else {
hmac, hmac ? strlen(hmac) : 0,
passphrase, passphrase ?
strlen(passphrase) : 0,
- fkey, fkey_len);
+ fkey ? fkey->data : NULL,
+ fkey ? fkey->len : 0);
/* Set CMODE notify type to network */
silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
/* Send command reply to sender */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
- SILC_STATUS_OK, 0, ident, 2,
+ SILC_STATUS_OK, 0, ident, 3,
2, tmp_id, tmp_len2,
- 3, tmp_mask, 4);
+ 3, tmp_mask, 4,
+ 4, fkey ? fkey->data : NULL,
+ fkey ? fkey->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
out:
channel->mode = old_mask;
- silc_free(fkey);
+ silc_buffer_free(fkey);
silc_free(channel_id);
silc_server_command_free(cmd);
}
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
SilcIDListData idata = (SilcIDListData)client;
- SilcChannelID *channel_id;
- SilcClientID *client_id;
+ SilcChannelID *channel_id = NULL;
+ SilcClientID *client_id = NULL;
SilcChannelEntry channel;
SilcClientEntry target_client;
SilcChannelClientEntry chl;
int notify = FALSE;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
SilcPublicKey founder_key = NULL;
- unsigned char *fkey = NULL;
- SilcUInt32 fkey_len = 0;
+ SilcBuffer fkey = NULL;
if (!client)
goto out;
notify = TRUE;
founder_key = channel->founder_key;
- fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
+ fkey = silc_pkcs_public_key_payload_encode(founder_key);
if (!fkey) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_AUTH_FAILED, 0);
idp->data, idp->len,
tmp_mask, 4,
tmp_id, tmp_len,
- fkey, fkey_len);
+ fkey ? fkey->data : NULL,
+ fkey ? fkey->len : 0);
/* Set CUMODE notify type to network */
silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
- silc_free(channel_id);
- silc_free(client_id);
silc_buffer_free(idp);
out:
- silc_free(fkey);
+ silc_free(channel_id);
+ silc_free(client_id);
+ silc_buffer_free(fkey);
silc_server_command_free(cmd);
}
silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
SILC_STATUS_ERR_AUTH_FAILED,
0);
+ SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
+ "nickname '%s' from %s", username,
+ client->nickname, cmd->sock->hostname));
goto out;
}
}
if (server->config->detach_disabled) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
- SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ 0);
goto out;
}
/* Send the user mode notify to notify that client is detached */
client->mode |= SILC_UMODE_DETACHED;
client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
+ client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
client->last_command = 0;
client->fast_command = 0;
silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
- if (server->server_type == SILC_SERVER && !server->standalone) {
+ if (server->server_type != SILC_ROUTER && !server->standalone) {
if (!cmd->pending) {
/* Send the command to router */
SilcBuffer tmpbuf;
SilcUInt16 old_ident;
+ SILC_LOG_DEBUG(("Forwarding WATCH to router"));
+
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);
/* Received reply from router, just send same data to the client. */
SilcServerCommandReplyContext reply = context2;
SilcStatus status;
+
+ SILC_LOG_DEBUG(("Received reply to WATCH from router"));
silc_command_get_status(reply->payload, &status, NULL);
silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
0);
if (!admin) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
SILC_STATUS_ERR_AUTH_FAILED, 0);
+ SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
+ "nickname '%s' from %s", username,
+ client->nickname, cmd->sock->hostname));
goto out;
}
}
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- SilcBuffer packet;
+ SilcBuffer packet, list, tmp2;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcChannelID *channel_id = NULL;
- unsigned char *id, *add, *del;
- SilcUInt32 id_len, tmp_len;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ unsigned char *id, *tmp;
+ SilcUInt32 id_len, len;
+ SilcArgumentPayload args;
+ SilcHashTableList htl;
+ SilcUInt32 type;
+ SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
goto out;
goto out;
}
- /* Get the new ban and add it to the ban list */
- add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (add) {
- if (!channel->ban_list)
- channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
- else
- channel->ban_list = silc_realloc(channel->ban_list,
- sizeof(*channel->ban_list) *
- (tmp_len +
- strlen(channel->ban_list) + 2));
- if (add[tmp_len - 1] == ',')
- add[tmp_len - 1] = '\0';
-
- strncat(channel->ban_list, add, tmp_len);
- strncat(channel->ban_list, ",", 1);
- }
-
- /* Get the ban to be removed and remove it from the list */
- del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (del && channel->ban_list) {
- char *start, *end, *n;
+ /* Get the ban information */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp) {
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(argc, tmp);
+ args = silc_argument_payload_parse(tmp + 2, len - 2, argc);
+ if (!args) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+ 0);
+ goto out;
+ }
- if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
- silc_free(channel->ban_list);
- channel->ban_list = NULL;
- } else {
- start = strstr(channel->ban_list, del);
- if (start && strlen(start) >= tmp_len) {
- end = start + tmp_len;
- n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
- strncat(n, channel->ban_list, start - channel->ban_list);
- strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
- end) - 1);
- silc_free(channel->ban_list);
- channel->ban_list = n;
+ /* Get the type of action */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp && len == 1) {
+ if (tmp[0] == 0x00) {
+ /* Allocate hash table for ban list if it doesn't exist yet */
+ if (!channel->ban_list)
+ channel->ban_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check for resource limit */
+ if (silc_hash_table_count(channel->ban_list) > 64) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_RESOURCE_LIMIT,
+ 0);
+ goto out;
+ }
}
+
+ /* Now add or delete the information. */
+ silc_server_inviteban_process(server, channel->ban_list,
+ (SilcUInt8)tmp[0], args);
+ }
+ silc_argument_payload_free(args);
+ }
+
+ /* Encode ban list */
+ list = NULL;
+ if (channel->ban_list) {
+ list = silc_buffer_alloc_size(2);
+ silc_buffer_format(list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->ban_list)),
+ SILC_STR_END);
+ silc_hash_table_list(channel->ban_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 1)
+ list = silc_argument_payload_encode_one(list, (char *)tmp2,
+ strlen((char *)tmp2), type);
+ else
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
}
+ silc_hash_table_list_reset(&htl);
}
/* Send the BAN notify type to our primary router. */
- if (add || del)
+ if (list)
silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
- SILC_BROADCAST(server), channel, add, del);
+ SILC_BROADCAST(server), channel,
+ silc_argument_get_arg_type(cmd->args, 2, NULL),
+ list);
/* Send the reply back to the client */
packet =
silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
SILC_STATUS_OK, 0, ident, 2,
2, id, id_len,
- 3, channel->ban_list,
- channel->ban_list ?
- strlen(channel->ban_list) -1 : 0);
+ 3, list ? list->data : NULL,
+ list ? list->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
+ silc_buffer_free(list);
out:
silc_free(channel_id);
id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
if (!id) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
+ SILC_STATUS_ERR_BAD_CHANNEL_ID, 0);
goto out;
}
}
SilcServerID *server_id = NULL;
SilcIDPayload idp = NULL;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- unsigned char *tmp, *pkdata;
- SilcUInt32 tmp_len, pklen;
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
SilcBuffer pk = NULL;
SilcIdType id_type;
SilcPublicKey public_key;
send it back. If they key does not exist then do not send it,
send just OK reply */
public_key = client->data.public_key;
- if (!public_key) {
- pkdata = NULL;
- pklen = 0;
- } else {
- 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,
- SILC_STR_UI_SHORT(tmp_len),
- SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
- SILC_STR_UI_XNSTRING(tmp, tmp_len),
- SILC_STR_END);
- silc_free(tmp);
- pkdata = pk->data;
- pklen = pk->len;
- }
+ if (public_key)
+ pk = silc_pkcs_public_key_payload_encode(public_key);
} else if (id_type == SILC_ID_SERVER) {
server_id = silc_id_payload_get_id(idp);
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(public_key, &tmp_len);
- pk = silc_buffer_alloc(4 + tmp_len);
- silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
- silc_buffer_format(pk,
- SILC_STR_UI_SHORT(tmp_len),
- SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
- SILC_STR_UI_XNSTRING(tmp, tmp_len),
- SILC_STR_END);
- silc_free(tmp);
- pkdata = pk->data;
- pklen = pk->len;
- }
+ if (public_key)
+ pk = silc_pkcs_public_key_payload_encode(public_key);
} else {
goto out;
}
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
- SILC_STATUS_OK, 0, ident,
- pkdata ? 2 : 1,
+ SILC_STATUS_OK, 0, ident, 2,
2, tmp, tmp_len,
- 3, pkdata, pklen);
+ 3, pk ? pk->data : NULL,
+ pk ? pk->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
- if (pk)
- silc_buffer_free(pk);
-
out:
if (idp)
silc_id_payload_free(idp);
+ silc_buffer_free(pk);
silc_free(client_id);
silc_free(server_id);
silc_server_command_free(cmd);
goto out;
}
- if (server->server_type == SILC_ROUTER &&
+ if (server->server_type == SILC_ROUTER && !server->backup_router &&
client->mode & SILC_UMODE_SERVER_OPERATOR) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);