5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
26 /* All functions that call the COMMAND_CHECK_STATUS or the
27 COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
33 if (status != SILC_STATUS_OK) \
37 #define COMMAND_CHECK_STATUS_LIST \
39 SILC_LOG_DEBUG(("Start")); \
40 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
41 if (status != SILC_STATUS_OK && \
42 status != SILC_STATUS_LIST_START && \
43 status != SILC_STATUS_LIST_ITEM && \
44 status != SILC_STATUS_LIST_END) \
48 /* Server command reply list. Not all commands have reply function as
49 they are never sent by server. More maybe added later if need appears. */
50 SilcServerCommandReply silc_command_reply_list[] =
52 SILC_SERVER_CMD_REPLY(whois, WHOIS),
53 SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
54 SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
55 SILC_SERVER_CMD_REPLY(info, INFO),
56 SILC_SERVER_CMD_REPLY(motd, MOTD),
57 SILC_SERVER_CMD_REPLY(join, JOIN),
58 SILC_SERVER_CMD_REPLY(users, USERS),
59 SILC_SERVER_CMD_REPLY(getkey, GETKEY),
64 /* Process received command reply. */
66 void silc_server_command_reply_process(SilcServer server,
67 SilcSocketConnection sock,
70 SilcServerCommandReply *cmd;
71 SilcServerCommandReplyContext ctx;
72 SilcCommandPayload payload;
76 SILC_LOG_DEBUG(("Start"));
78 /* Get command reply payload from packet */
79 payload = silc_command_payload_parse(buffer);
81 /* Silently ignore bad reply packet */
82 SILC_LOG_DEBUG(("Bad command reply packet"));
86 /* Allocate command reply context. This must be free'd by the
87 command reply routine receiving it. */
88 ctx = silc_calloc(1, sizeof(*ctx));
90 ctx->sock = silc_socket_dup(sock);
91 ctx->payload = payload;
92 ctx->args = silc_command_get_args(ctx->payload);
93 ident = silc_command_get_ident(ctx->payload);
95 /* Check for pending commands and mark to be exeucted */
96 silc_server_command_pending_check(server, ctx,
97 silc_command_get(ctx->payload), ident);
99 /* Execute command reply */
100 command = silc_command_get(ctx->payload);
101 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
102 if (cmd->cmd == command)
105 if (cmd == NULL || !cmd->cb) {
106 silc_server_command_reply_free(ctx);
113 /* Free command reply context and its internals. */
115 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
118 silc_command_free_payload(cmd->payload);
120 silc_socket_free(cmd->sock); /* Decrease the reference counter */
125 /* Caches the received WHOIS information. */
128 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
130 SilcServer server = cmd->server;
131 unsigned char *tmp, *id_data;
132 char *nickname, *username, *realname, *servername = NULL;
133 SilcClientID *client_id;
134 SilcClientEntry client;
135 SilcIDCacheEntry cache = NULL;
138 uint32 mode = 0, len, id_len;
140 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
141 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
142 username = silc_argument_get_arg_type(cmd->args, 4, &len);
143 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
144 if (!id_data || !nickname || !username || !realname) {
145 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
146 nickname ? nickname : "",
147 username ? username : "",
148 realname ? realname : ""));
152 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
154 SILC_GET32_MSB(mode, tmp);
156 client_id = silc_id_payload_parse_id(id_data, id_len);
160 /* Check if we have this client cached already. */
162 client = silc_idlist_find_client_by_id(server->local_list, client_id,
165 client = silc_idlist_find_client_by_id(server->global_list,
171 /* If router did not find such Client ID in its lists then this must
172 be bogus client or some router in the net is buggy. */
173 if (server->server_type == SILC_ROUTER)
176 /* Take hostname out of nick string if it includes it. */
177 if (strchr(nickname, '@')) {
178 int len = strcspn(nickname, "@");
179 nick = silc_calloc(len + 1, sizeof(char));
180 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
181 memcpy(nick, nickname, len);
182 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
184 nick = strdup(nickname);
187 /* We don't have that client anywhere, add it. The client is added
188 to global list since server didn't have it in the lists so it must be
190 client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
192 strdup(realname), client_id,
193 cmd->sock->user_data, NULL);
197 client->data.registered = TRUE;
199 client->servername = servername;
201 /* We have the client already, update the data */
203 SILC_LOG_DEBUG(("Updating client data"));
205 /* Take hostname out of nick string if it includes it. */
206 if (strchr(nickname, '@')) {
207 int len = strcspn(nickname, "@");
208 nick = silc_calloc(len + 1, sizeof(char));
209 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
210 memcpy(nick, nickname, len);
211 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
213 nick = strdup(nickname);
216 if (client->nickname)
217 silc_free(client->nickname);
218 if (client->username)
219 silc_free(client->username);
220 if (client->userinfo)
221 silc_free(client->userinfo);
223 client->nickname = nick;
224 client->username = strdup(username);
225 client->userinfo = strdup(realname);
227 client->servername = servername;
231 cache->data_len = strlen(nick);
232 silc_idcache_sort_by_data(global ? server->global_list->clients :
233 server->local_list->clients);
236 silc_free(client_id);
242 /* Reiceved reply for WHOIS command. We sent the whois request to our
243 primary router, if we are normal server, and thus has now received reply
244 to the command. We will figure out what client originally sent us the
245 command and will send the reply to it. If we are router we will figure
246 out who server sent us the command and send reply to that one. */
248 SILC_SERVER_CMD_REPLY_FUNC(whois)
250 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
251 SilcCommandStatus status;
253 COMMAND_CHECK_STATUS_LIST;
255 if (!silc_server_command_reply_whois_save(cmd))
258 /* Pending callbacks are not executed if this was an list entry */
259 if (status != SILC_STATUS_OK &&
260 status != SILC_STATUS_LIST_END) {
261 silc_server_command_reply_free(cmd);
266 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
267 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
268 silc_server_command_reply_free(cmd);
271 /* Caches the received WHOWAS information for a short period of time. */
274 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
276 SilcServer server = cmd->server;
278 unsigned char *id_data;
279 char *nickname, *username, *realname, *servername = NULL;
280 SilcClientID *client_id;
281 SilcClientEntry client;
282 SilcIDCacheEntry cache = NULL;
286 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
287 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
288 username = silc_argument_get_arg_type(cmd->args, 4, &len);
289 if (!id_data || !nickname || !username)
292 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
294 client_id = silc_id_payload_parse_id(id_data, id_len);
298 /* Check if we have this client cached already. */
300 client = silc_idlist_find_client_by_id(server->local_list, client_id,
303 client = silc_idlist_find_client_by_id(server->global_list,
309 /* If router did not find such Client ID in its lists then this must
310 be bogus client or some router in the net is buggy. */
311 if (server->server_type == SILC_ROUTER)
314 /* Take hostname out of nick string if it includes it. */
315 if (strchr(nickname, '@')) {
316 int len = strcspn(nickname, "@");
317 nick = silc_calloc(len + 1, sizeof(char));
318 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
319 memcpy(nick, nickname, len);
320 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
322 nick = strdup(nickname);
325 /* We don't have that client anywhere, add it. The client is added
326 to global list since server didn't have it in the lists so it must be
328 client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
329 strdup(username), strdup(realname),
330 silc_id_dup(client_id, SILC_ID_CLIENT),
331 cmd->sock->user_data, NULL);
335 client->data.registered = FALSE;
336 client = silc_idlist_find_client_by_id(server->global_list,
338 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
339 client->servername = servername;
341 /* We have the client already, update the data */
343 /* Take hostname out of nick string if it includes it. */
344 if (strchr(nickname, '@')) {
345 int len = strcspn(nickname, "@");
346 nick = silc_calloc(len + 1, sizeof(char));
347 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
348 memcpy(nick, nickname, len);
349 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
351 nick = strdup(nickname);
354 if (client->nickname)
355 silc_free(client->nickname);
356 if (client->username)
357 silc_free(client->username);
359 client->nickname = nick;
360 client->username = strdup(username);
361 client->servername = servername;
365 cache->data_len = strlen(nick);
366 silc_idcache_sort_by_data(global ? server->global_list->clients :
367 server->local_list->clients);
371 silc_free(client_id);
376 /* Received reply for WHOWAS command. Cache the client information only for
377 a short period of time. */
379 SILC_SERVER_CMD_REPLY_FUNC(whowas)
381 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
382 SilcCommandStatus status;
384 COMMAND_CHECK_STATUS_LIST;
386 if (!silc_server_command_reply_whowas_save(cmd))
389 /* Pending callbacks are not executed if this was an list entry */
390 if (status != SILC_STATUS_OK &&
391 status != SILC_STATUS_LIST_END) {
392 silc_server_command_reply_free(cmd);
397 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
398 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
399 silc_server_command_reply_free(cmd);
402 /* Caches the received IDENTIFY information. */
405 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
407 SilcServer server = cmd->server;
409 unsigned char *id_data;
410 char *nickname, *username;
411 SilcClientID *client_id;
412 SilcClientEntry client;
413 SilcIDCacheEntry cache = NULL;
417 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
418 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
419 username = silc_argument_get_arg_type(cmd->args, 4, &len);
423 client_id = silc_id_payload_parse_id(id_data, id_len);
427 /* Check if we have this client cached already. */
429 client = silc_idlist_find_client_by_id(server->local_list, client_id,
432 client = silc_idlist_find_client_by_id(server->global_list,
438 /* If router did not find such Client ID in its lists then this must
439 be bogus client or some router in the net is buggy. */
440 if (server->server_type == SILC_ROUTER)
443 /* Take hostname out of nick string if it includes it. */
445 if (strchr(nickname, '@')) {
446 int len = strcspn(nickname, "@");
447 nick = silc_calloc(len + 1, sizeof(char));
448 memcpy(nick, nickname, len);
450 nick = strdup(nickname);
454 /* We don't have that client anywhere, add it. The client is added
455 to global list since server didn't have it in the lists so it must be
457 client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
458 username ? strdup(username) : NULL, NULL,
459 client_id, cmd->sock->user_data, NULL);
460 client->data.registered = TRUE;
462 /* We have the client already, update the data */
464 SILC_LOG_DEBUG(("Updating client data"));
466 /* Take hostname out of nick string if it includes it. */
468 if (strchr(nickname, '@')) {
469 int len = strcspn(nickname, "@");
470 nick = silc_calloc(len + 1, sizeof(char));
471 memcpy(nick, nickname, len);
473 nick = strdup(nickname);
477 if (nickname && client->nickname)
478 silc_free(client->nickname);
481 client->nickname = nick;
483 if (username && client->username) {
484 silc_free(client->username);
485 client->username = strdup(username);
488 if (nickname && cache) {
490 cache->data_len = strlen(nick);
491 silc_idcache_sort_by_data(global ? server->global_list->clients :
492 server->local_list->clients);
495 silc_free(client_id);
501 /* Received reply for forwarded IDENTIFY command. We have received the
502 requested identify information now and we will cache it. After this we
503 will call the pending command so that the requestee gets the information
506 SILC_SERVER_CMD_REPLY_FUNC(identify)
508 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
509 SilcCommandStatus status;
511 COMMAND_CHECK_STATUS_LIST;
513 if (!silc_server_command_reply_identify_save(cmd))
516 /* Pending callbacks are not executed if this was an list entry */
517 if (status != SILC_STATUS_OK &&
518 status != SILC_STATUS_LIST_END) {
519 silc_server_command_reply_free(cmd);
524 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
525 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
526 silc_server_command_reply_free(cmd);
529 /* Received reply fro INFO command. Cache the server and its information */
531 SILC_SERVER_CMD_REPLY_FUNC(info)
533 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
534 SilcServer server = cmd->server;
535 SilcCommandStatus status;
536 SilcServerEntry entry;
537 SilcServerID *server_id;
539 unsigned char *tmp, *name;
541 COMMAND_CHECK_STATUS;
544 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
547 server_id = silc_id_payload_parse_id(tmp, tmp_len);
552 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
556 entry = silc_idlist_find_server_by_id(server->local_list, server_id, NULL);
558 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
561 /* Add the server to global list */
562 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
563 entry = silc_idlist_add_server(server->global_list, name, 0,
564 server_id, NULL, NULL);
566 silc_free(server_id);
572 /* Get the info string */
573 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
577 entry->server_info = tmp ? strdup(tmp) : NULL;
580 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
581 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
582 silc_server_command_reply_free(cmd);
585 /* Received reply fro MOTD command. */
587 SILC_SERVER_CMD_REPLY_FUNC(motd)
589 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
590 SilcServer server = cmd->server;
591 SilcCommandStatus status;
592 SilcServerEntry entry = NULL;
593 SilcServerID *server_id;
597 COMMAND_CHECK_STATUS;
600 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
603 server_id = silc_id_payload_parse_id(tmp, tmp_len);
607 entry = silc_idlist_find_server_by_id(server->local_list, server_id, NULL);
609 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
616 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
623 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
624 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
625 silc_server_command_reply_free(cmd);
631 /* Received reply for forwarded JOIN command. Router has created or joined
632 the client to the channel. We save some channel information locally
635 SILC_SERVER_CMD_REPLY_FUNC(join)
637 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
638 SilcServer server = cmd->server;
639 SilcIDCacheEntry cache = NULL;
640 SilcCommandStatus status;
642 SilcClientID *client_id = NULL;
643 SilcChannelEntry entry;
644 SilcHmac hmac = NULL;
645 uint32 id_len, len, list_count;
646 unsigned char *id_string;
647 char *channel_name, *tmp;
648 uint32 mode, created;
649 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
651 COMMAND_CHECK_STATUS;
653 /* Get channel name */
654 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
659 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
664 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
667 client_id = silc_id_payload_parse_id(tmp, len);
672 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
675 SILC_GET32_MSB(mode, tmp);
677 /* Get created boolean value */
678 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
681 SILC_GET32_MSB(created, tmp);
682 if (created != 0 && created != 1)
685 /* Get channel key */
686 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
688 keyp = silc_buffer_alloc(len);
689 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
690 silc_buffer_put(keyp, tmp, len);
693 id = silc_id_payload_parse_id(id_string, id_len);
698 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
700 if (!silc_hmac_alloc(tmp, NULL, &hmac))
704 /* Get the list count */
705 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
708 SILC_GET32_MSB(list_count, tmp);
710 /* Get Client ID list */
711 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
715 client_id_list = silc_buffer_alloc(len);
716 silc_buffer_pull_tail(client_id_list, len);
717 silc_buffer_put(client_id_list, tmp, len);
719 /* Get client mode list */
720 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
724 client_mode_list = silc_buffer_alloc(len);
725 silc_buffer_pull_tail(client_mode_list, len);
726 silc_buffer_put(client_mode_list, tmp, len);
728 /* See whether we already have the channel. */
729 entry = silc_idlist_find_channel_by_name(server->local_list,
730 channel_name, &cache);
732 /* Add new channel */
734 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
735 (created == 0 ? "existing" : "created"), channel_name,
736 silc_id_render(id, SILC_ID_CHANNEL)));
738 /* Add the channel to our local list. */
739 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
740 SILC_CHANNEL_MODE_NONE, id,
741 server->router, NULL, hmac);
747 /* The entry exists. */
749 silc_free(cache->id);
751 cache->id = entry->id;
753 /* Remove the founder auth data if the mode is not set but we have
755 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
756 silc_pkcs_public_key_free(entry->founder_key);
757 if (entry->founder_passwd) {
758 silc_free(entry->founder_passwd);
759 entry->founder_passwd = NULL;
764 if (entry->hmac_name && hmac) {
765 silc_free(entry->hmac_name);
766 entry->hmac_name = strdup(hmac->hmac->name);
769 /* Get the ban list */
770 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
773 silc_free(entry->ban_list);
774 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
775 memcpy(entry->ban_list, tmp, len);
778 /* Get the invite list */
779 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
781 if (entry->invite_list)
782 silc_free(entry->invite_list);
783 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
784 memcpy(entry->invite_list, tmp, len);
788 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
791 silc_free(entry->topic);
792 entry->topic = strdup(tmp);
795 /* If channel was not created we know there is global users on the
797 entry->global_users = (created == 0 ? TRUE : FALSE);
799 /* If channel was just created the mask must be zero */
800 if (!entry->global_users && mode) {
801 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
802 "new channel, forcing it to zero", cmd->sock->hostname));
806 /* Save channel mode */
809 /* Save channel key */
810 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
811 silc_server_save_channel_key(server, keyp, entry);
813 silc_buffer_free(keyp);
815 /* Save the users to the channel */
816 silc_server_save_users_on_channel(server, cmd->sock, entry,
817 client_id, client_id_list,
818 client_mode_list, list_count);
821 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
822 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
824 silc_free(client_id);
825 silc_server_command_reply_free(cmd);
828 silc_buffer_free(client_id_list);
829 if (client_mode_list)
830 silc_buffer_free(client_mode_list);
833 SILC_SERVER_CMD_REPLY_FUNC(users)
835 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
836 SilcServer server = cmd->server;
837 SilcCommandStatus status;
838 SilcChannelEntry channel;
839 SilcChannelID *channel_id = NULL;
840 SilcBuffer client_id_list;
841 SilcBuffer client_mode_list;
846 COMMAND_CHECK_STATUS;
849 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
852 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
856 /* Get channel entry */
857 channel = silc_idlist_find_channel_by_id(server->local_list,
860 channel = silc_idlist_find_channel_by_id(server->global_list,
866 /* Get the list count */
867 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
870 SILC_GET32_MSB(list_count, tmp);
872 /* Get Client ID list */
873 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
877 client_id_list = silc_buffer_alloc(tmp_len);
878 silc_buffer_pull_tail(client_id_list, tmp_len);
879 silc_buffer_put(client_id_list, tmp, tmp_len);
881 /* Get client mode list */
882 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
886 client_mode_list = silc_buffer_alloc(tmp_len);
887 silc_buffer_pull_tail(client_mode_list, tmp_len);
888 silc_buffer_put(client_mode_list, tmp, tmp_len);
890 /* Save the users to the channel */
891 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
892 client_id_list, client_mode_list,
895 silc_buffer_free(client_id_list);
896 silc_buffer_free(client_mode_list);
899 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
900 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
901 silc_free(channel_id);
902 silc_server_command_reply_free(cmd);
905 SILC_SERVER_CMD_REPLY_FUNC(getkey)
907 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
908 SilcServer server = cmd->server;
909 SilcCommandStatus status;
910 SilcClientEntry client = NULL;
911 SilcServerEntry server_entry = NULL;
912 SilcClientID *client_id = NULL;
913 SilcServerID *server_id = NULL;
915 unsigned char *tmp, *pk;
918 SilcIDPayload idp = NULL;
920 SilcPublicKey public_key = NULL;
922 COMMAND_CHECK_STATUS;
924 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
927 idp = silc_id_payload_parse_data(tmp, len);
931 /* Get the public key payload */
932 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
936 /* Decode the public key */
938 SILC_GET16_MSB(pk_len, tmp);
939 SILC_GET16_MSB(type, tmp + 2);
942 if (type != SILC_SKE_PK_TYPE_SILC)
945 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
948 id_type = silc_id_payload_get_type(idp);
949 if (id_type == SILC_ID_CLIENT) {
950 client_id = silc_id_payload_get_id(idp);
952 client = silc_idlist_find_client_by_id(server->local_list, client_id,
955 client = silc_idlist_find_client_by_id(server->global_list,
961 client->data.public_key = public_key;
962 } else if (id_type == SILC_ID_SERVER) {
963 server_id = silc_id_payload_get_id(idp);
965 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
968 server_entry = silc_idlist_find_server_by_id(server->global_list,
974 server_entry->data.public_key = public_key;
980 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
981 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
983 silc_id_payload_free(idp);
984 silc_free(client_id);
985 silc_free(server_id);
987 silc_pkcs_public_key_free(public_key);
988 silc_server_command_reply_free(cmd);