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_payload_free(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;
137 uint32 mode = 0, len, id_len;
139 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
140 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
141 username = silc_argument_get_arg_type(cmd->args, 4, &len);
142 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
143 if (!id_data || !nickname || !username || !realname) {
144 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
145 nickname ? nickname : "",
146 username ? username : "",
147 realname ? realname : ""));
151 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
153 SILC_GET32_MSB(mode, tmp);
155 client_id = silc_id_payload_parse_id(id_data, id_len);
159 /* Check if we have this client cached already. */
161 client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
163 client = silc_idlist_find_client_by_id(server->global_list, client_id,
169 /* If router did not find such Client ID in its lists then this must
170 be bogus client or some router in the net is buggy. */
171 if (server->server_type == SILC_ROUTER)
174 /* Take hostname out of nick string if it includes it. */
175 if (strchr(nickname, '@')) {
176 int len = strcspn(nickname, "@");
177 nick = silc_calloc(len + 1, sizeof(char));
178 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
179 memcpy(nick, nickname, len);
180 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
182 nick = strdup(nickname);
185 /* We don't have that client anywhere, add it. The client is added
186 to global list since server didn't have it in the lists so it must be
188 client = silc_idlist_add_client(server->global_list, nick,
190 strdup(realname), client_id,
191 cmd->sock->user_data, NULL);
195 client->data.registered = TRUE;
197 client->servername = servername;
199 /* We have the client already, update the data */
201 SILC_LOG_DEBUG(("Updating client data"));
203 /* Take hostname out of nick string if it includes it. */
204 if (strchr(nickname, '@')) {
205 int len = strcspn(nickname, "@");
206 nick = silc_calloc(len + 1, sizeof(char));
207 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
208 memcpy(nick, nickname, len);
209 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
211 nick = strdup(nickname);
214 if (client->nickname)
215 silc_free(client->nickname);
216 if (client->username)
217 silc_free(client->username);
218 if (client->userinfo)
219 silc_free(client->userinfo);
221 client->nickname = nick;
222 client->username = strdup(username);
223 client->userinfo = strdup(realname);
225 client->servername = servername;
227 /* Remove the old cache entry and create a new one */
228 silc_idcache_del_by_context(global ? server->global_list->clients :
229 server->local_list->clients, client);
230 silc_idcache_add(global ? server->global_list->clients :
231 server->local_list->clients, nick, client->id,
233 silc_free(client_id);
239 /* Reiceved reply for WHOIS command. We sent the whois request to our
240 primary router, if we are normal server, and thus has now received reply
241 to the command. We will figure out what client originally sent us the
242 command and will send the reply to it. If we are router we will figure
243 out who server sent us the command and send reply to that one. */
245 SILC_SERVER_CMD_REPLY_FUNC(whois)
247 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
248 SilcCommandStatus status;
250 COMMAND_CHECK_STATUS_LIST;
252 if (!silc_server_command_reply_whois_save(cmd))
255 /* Pending callbacks are not executed if this was an list entry */
256 if (status != SILC_STATUS_OK &&
257 status != SILC_STATUS_LIST_END) {
258 silc_server_command_reply_free(cmd);
263 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
264 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
265 silc_server_command_reply_free(cmd);
268 /* Caches the received WHOWAS information for a short period of time. */
271 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
273 SilcServer server = cmd->server;
275 unsigned char *id_data;
276 char *nickname, *username, *realname, *servername = NULL;
277 SilcClientID *client_id;
278 SilcClientEntry client;
279 SilcIDCacheEntry cache = NULL;
283 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
284 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
285 username = silc_argument_get_arg_type(cmd->args, 4, &len);
286 if (!id_data || !nickname || !username)
289 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
291 client_id = silc_id_payload_parse_id(id_data, id_len);
295 /* Check if we have this client cached already. */
297 client = silc_idlist_find_client_by_id(server->local_list, client_id,
300 client = silc_idlist_find_client_by_id(server->global_list,
306 /* If router did not find such Client ID in its lists then this must
307 be bogus client or some router in the net is buggy. */
308 if (server->server_type == SILC_ROUTER)
311 /* Take hostname out of nick string if it includes it. */
312 if (strchr(nickname, '@')) {
313 int len = strcspn(nickname, "@");
314 nick = silc_calloc(len + 1, sizeof(char));
315 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
316 memcpy(nick, nickname, len);
317 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
319 nick = strdup(nickname);
322 /* We don't have that client anywhere, add it. The client is added
323 to global list since server didn't have it in the lists so it must be
325 client = silc_idlist_add_client(server->global_list, nick,
326 strdup(username), strdup(realname),
327 silc_id_dup(client_id, SILC_ID_CLIENT),
328 cmd->sock->user_data, NULL);
332 client->data.registered = FALSE;
333 client = silc_idlist_find_client_by_id(server->global_list,
335 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
336 client->servername = servername;
338 /* We have the client already, update the data */
340 /* Take hostname out of nick string if it includes it. */
341 if (strchr(nickname, '@')) {
342 int len = strcspn(nickname, "@");
343 nick = silc_calloc(len + 1, sizeof(char));
344 servername = silc_calloc((strlen(nickname) - len) + 1, sizeof(char));
345 memcpy(nick, nickname, len);
346 memcpy(servername, nickname + len + 1, strlen(nickname) - len);
348 nick = strdup(nickname);
351 if (client->nickname)
352 silc_free(client->nickname);
353 if (client->username)
354 silc_free(client->username);
356 client->nickname = nick;
357 client->username = strdup(username);
358 client->servername = servername;
360 /* Remove the old cache entry and create a new one */
361 silc_idcache_del_by_context(global ? server->global_list->clients :
362 server->local_list->clients, client);
363 silc_idcache_add(global ? server->global_list->clients :
364 server->local_list->clients, nick, client->id,
368 silc_free(client_id);
373 /* Received reply for WHOWAS command. Cache the client information only for
374 a short period of time. */
376 SILC_SERVER_CMD_REPLY_FUNC(whowas)
378 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
379 SilcCommandStatus status;
381 COMMAND_CHECK_STATUS_LIST;
383 if (!silc_server_command_reply_whowas_save(cmd))
386 /* Pending callbacks are not executed if this was an list entry */
387 if (status != SILC_STATUS_OK &&
388 status != SILC_STATUS_LIST_END) {
389 silc_server_command_reply_free(cmd);
394 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
395 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
396 silc_server_command_reply_free(cmd);
399 /* Caches the received IDENTIFY information. */
402 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
404 SilcServer server = cmd->server;
406 unsigned char *id_data;
408 SilcClientID *client_id = NULL;
409 SilcServerID *server_id = NULL;
410 SilcChannelID *channel_id = NULL;
411 SilcClientEntry client;
412 SilcServerEntry server_entry;
413 SilcChannelEntry channel;
416 SilcIDPayload idp = NULL;
419 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
422 idp = silc_id_payload_parse_data(id_data, id_len);
426 name = silc_argument_get_arg_type(cmd->args, 3, &len);
427 info = silc_argument_get_arg_type(cmd->args, 4, &len);
429 id_type = silc_id_payload_get_type(idp);
433 client_id = silc_id_payload_get_id(idp);
437 SILC_LOG_DEBUG(("Received client information"));
439 client = silc_idlist_find_client_by_id(server->local_list,
442 client = silc_idlist_find_client_by_id(server->global_list, client_id,
447 /* If router did not find such Client ID in its lists then this must
448 be bogus client or some router in the net is buggy. */
449 if (server->server_type == SILC_ROUTER)
452 /* Take hostname out of nick string if it includes it. */
454 if (strchr(name, '@')) {
455 int len = strcspn(name, "@");
456 nick = silc_calloc(len + 1, sizeof(char));
457 memcpy(nick, name, len);
463 /* We don't have that client anywhere, add it. The client is added
464 to global list since server didn't have it in the lists so it must be
466 client = silc_idlist_add_client(server->global_list, nick,
467 info ? strdup(info) : NULL, NULL,
468 client_id, cmd->sock->user_data, NULL);
469 client->data.registered = TRUE;
471 /* We have the client already, update the data */
473 SILC_LOG_DEBUG(("Updating client data"));
475 /* Take hostname out of nick string if it includes it. */
477 if (strchr(name, '@')) {
478 int len = strcspn(name, "@");
479 nick = silc_calloc(len + 1, sizeof(char));
480 memcpy(nick, name, len);
486 if (name && client->nickname)
487 silc_free(client->nickname);
490 client->nickname = nick;
492 if (info && client->username) {
493 silc_free(client->username);
494 client->username = strdup(info);
497 /* Remove the old cache entry and create a new one */
499 silc_idcache_del_by_context(global ? server->global_list->clients :
500 server->local_list->clients, client);
501 silc_idcache_add(global ? server->global_list->clients :
502 server->local_list->clients, nick, client->id,
506 silc_free(client_id);
512 server_id = silc_id_payload_get_id(idp);
516 SILC_LOG_DEBUG(("Received server information"));
518 server_entry = silc_idlist_find_server_by_id(server->local_list,
521 server_entry = silc_idlist_find_server_by_id(server->global_list,
524 /* If router did not find such Server ID in its lists then this must
525 be bogus client or some router in the net is buggy. */
526 if (server->server_type == SILC_ROUTER)
529 /* We don't have that server anywhere, add it. */
530 server_entry = silc_idlist_add_server(server->global_list,
532 server_id, NULL, NULL);
534 silc_free(server_id);
540 silc_free(server_id);
543 case SILC_ID_CHANNEL:
544 channel_id = silc_id_payload_get_id(idp);
548 SILC_LOG_DEBUG(("Received channel information"));
550 channel = silc_idlist_find_channel_by_id(server->local_list,
553 channel = silc_idlist_find_channel_by_id(server->global_list, channel_id,
556 /* If router did not find such Server ID in its lists then this must
557 be bogus client or some router in the net is buggy. */
558 if (server->server_type == SILC_ROUTER)
561 /* We don't have that server anywhere, add it. */
562 channel = silc_idlist_add_channel(server->global_list, strdup(name),
563 SILC_CHANNEL_MODE_NONE, channel_id,
564 server->router->connection,
567 silc_free(channel_id);
573 silc_free(channel_id);
577 silc_id_payload_free(idp);
581 silc_id_payload_free(idp);
585 /* Received reply for forwarded IDENTIFY command. We have received the
586 requested identify information now and we will cache it. After this we
587 will call the pending command so that the requestee gets the information
590 SILC_SERVER_CMD_REPLY_FUNC(identify)
592 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
593 SilcCommandStatus status;
595 COMMAND_CHECK_STATUS_LIST;
597 if (!silc_server_command_reply_identify_save(cmd))
600 /* Pending callbacks are not executed if this was an list entry */
601 if (status != SILC_STATUS_OK &&
602 status != SILC_STATUS_LIST_END) {
603 silc_server_command_reply_free(cmd);
608 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
609 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
610 silc_server_command_reply_free(cmd);
613 /* Received reply fro INFO command. Cache the server and its information */
615 SILC_SERVER_CMD_REPLY_FUNC(info)
617 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
618 SilcServer server = cmd->server;
619 SilcCommandStatus status;
620 SilcServerEntry entry;
621 SilcServerID *server_id;
623 unsigned char *tmp, *name;
625 COMMAND_CHECK_STATUS;
628 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
631 server_id = silc_id_payload_parse_id(tmp, tmp_len);
636 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
640 entry = silc_idlist_find_server_by_id(server->local_list, server_id, NULL);
642 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
645 /* Add the server to global list */
646 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
647 entry = silc_idlist_add_server(server->global_list, name, 0,
648 server_id, NULL, NULL);
650 silc_free(server_id);
656 /* Get the info string */
657 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
661 entry->server_info = tmp ? strdup(tmp) : NULL;
664 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
665 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
666 silc_server_command_reply_free(cmd);
669 /* Received reply fro MOTD command. */
671 SILC_SERVER_CMD_REPLY_FUNC(motd)
673 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
674 SilcServer server = cmd->server;
675 SilcCommandStatus status;
676 SilcServerEntry entry = NULL;
677 SilcServerID *server_id;
681 COMMAND_CHECK_STATUS;
684 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
687 server_id = silc_id_payload_parse_id(tmp, tmp_len);
691 entry = silc_idlist_find_server_by_id(server->local_list, server_id, NULL);
693 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
700 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
707 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
708 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
709 silc_server_command_reply_free(cmd);
715 /* Received reply for forwarded JOIN command. Router has created or joined
716 the client to the channel. We save some channel information locally
719 SILC_SERVER_CMD_REPLY_FUNC(join)
721 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
722 SilcServer server = cmd->server;
723 SilcIDCacheEntry cache = NULL;
724 SilcCommandStatus status;
726 SilcClientID *client_id = NULL;
727 SilcChannelEntry entry;
728 SilcHmac hmac = NULL;
729 uint32 id_len, len, list_count;
730 unsigned char *id_string;
731 char *channel_name, *tmp;
732 uint32 mode, created;
733 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
735 COMMAND_CHECK_STATUS;
737 /* Get channel name */
738 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
743 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
748 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
751 client_id = silc_id_payload_parse_id(tmp, len);
756 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
759 SILC_GET32_MSB(mode, tmp);
761 /* Get created boolean value */
762 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
765 SILC_GET32_MSB(created, tmp);
766 if (created != 0 && created != 1)
769 /* Get channel key */
770 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
772 keyp = silc_buffer_alloc(len);
773 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
774 silc_buffer_put(keyp, tmp, len);
777 id = silc_id_payload_parse_id(id_string, id_len);
782 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
784 if (!silc_hmac_alloc(tmp, NULL, &hmac))
788 /* Get the list count */
789 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
792 SILC_GET32_MSB(list_count, tmp);
794 /* Get Client ID list */
795 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
799 client_id_list = silc_buffer_alloc(len);
800 silc_buffer_pull_tail(client_id_list, len);
801 silc_buffer_put(client_id_list, tmp, len);
803 /* Get client mode list */
804 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
808 client_mode_list = silc_buffer_alloc(len);
809 silc_buffer_pull_tail(client_mode_list, len);
810 silc_buffer_put(client_mode_list, tmp, len);
812 /* See whether we already have the channel. */
813 entry = silc_idlist_find_channel_by_name(server->local_list,
814 channel_name, &cache);
816 /* Add new channel */
818 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
819 (created == 0 ? "existing" : "created"), channel_name,
820 silc_id_render(id, SILC_ID_CHANNEL)));
822 /* Add the channel to our local list. */
823 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
824 SILC_CHANNEL_MODE_NONE, id,
825 server->router, NULL, hmac);
831 /* The entry exists. */
833 silc_free(cache->id);
835 cache->id = entry->id;
837 /* Remove the founder auth data if the mode is not set but we have
839 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
840 silc_pkcs_public_key_free(entry->founder_key);
841 if (entry->founder_passwd) {
842 silc_free(entry->founder_passwd);
843 entry->founder_passwd = NULL;
848 if (entry->hmac_name && hmac) {
849 silc_free(entry->hmac_name);
850 entry->hmac_name = strdup(hmac->hmac->name);
853 /* Get the ban list */
854 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
857 silc_free(entry->ban_list);
858 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
859 memcpy(entry->ban_list, tmp, len);
862 /* Get the invite list */
863 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
865 if (entry->invite_list)
866 silc_free(entry->invite_list);
867 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
868 memcpy(entry->invite_list, tmp, len);
872 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
875 silc_free(entry->topic);
876 entry->topic = strdup(tmp);
879 /* If channel was not created we know there is global users on the
881 entry->global_users = (created == 0 ? TRUE : FALSE);
883 /* If channel was just created the mask must be zero */
884 if (!entry->global_users && mode) {
885 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
886 "new channel, forcing it to zero", cmd->sock->hostname));
890 /* Save channel mode */
893 /* Save channel key */
894 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
895 silc_server_save_channel_key(server, keyp, entry);
897 silc_buffer_free(keyp);
899 /* Save the users to the channel */
900 silc_server_save_users_on_channel(server, cmd->sock, entry,
901 client_id, client_id_list,
902 client_mode_list, list_count);
905 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
906 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
908 silc_free(client_id);
909 silc_server_command_reply_free(cmd);
912 silc_buffer_free(client_id_list);
913 if (client_mode_list)
914 silc_buffer_free(client_mode_list);
917 SILC_SERVER_CMD_REPLY_FUNC(users)
919 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
920 SilcServer server = cmd->server;
921 SilcCommandStatus status;
922 SilcChannelEntry channel;
923 SilcChannelID *channel_id = NULL;
924 SilcBuffer client_id_list;
925 SilcBuffer client_mode_list;
930 COMMAND_CHECK_STATUS;
933 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
936 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
940 /* Get channel entry */
941 channel = silc_idlist_find_channel_by_id(server->local_list,
944 channel = silc_idlist_find_channel_by_id(server->global_list,
949 if (server->server_type == SILC_ROUTER)
952 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
953 silc_server_send_command(server, server->router->connection,
954 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
955 1, 5, idp->data, idp->len);
956 silc_buffer_free(idp);
958 /* Register pending command callback. After we've received the channel
959 information we will reprocess this command reply by re-calling this
960 USERS command reply callback. */
961 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
963 NULL, silc_server_command_reply_users, cmd);
968 /* Get the list count */
969 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
972 SILC_GET32_MSB(list_count, tmp);
974 /* Get Client ID list */
975 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
979 client_id_list = silc_buffer_alloc(tmp_len);
980 silc_buffer_pull_tail(client_id_list, tmp_len);
981 silc_buffer_put(client_id_list, tmp, tmp_len);
983 /* Get client mode list */
984 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
988 client_mode_list = silc_buffer_alloc(tmp_len);
989 silc_buffer_pull_tail(client_mode_list, tmp_len);
990 silc_buffer_put(client_mode_list, tmp, tmp_len);
992 /* Save the users to the channel */
993 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
994 client_id_list, client_mode_list,
997 silc_buffer_free(client_id_list);
998 silc_buffer_free(client_mode_list);
1001 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1002 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1003 silc_free(channel_id);
1004 silc_server_command_reply_free(cmd);
1007 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1009 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1010 SilcServer server = cmd->server;
1011 SilcCommandStatus status;
1012 SilcClientEntry client = NULL;
1013 SilcServerEntry server_entry = NULL;
1014 SilcClientID *client_id = NULL;
1015 SilcServerID *server_id = NULL;
1017 unsigned char *tmp, *pk;
1020 SilcIDPayload idp = NULL;
1022 SilcPublicKey public_key = NULL;
1024 COMMAND_CHECK_STATUS;
1026 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1029 idp = silc_id_payload_parse_data(tmp, len);
1033 /* Get the public key payload */
1034 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1038 /* Decode the public key */
1040 SILC_GET16_MSB(pk_len, tmp);
1041 SILC_GET16_MSB(type, tmp + 2);
1044 if (type != SILC_SKE_PK_TYPE_SILC)
1047 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1050 id_type = silc_id_payload_get_type(idp);
1051 if (id_type == SILC_ID_CLIENT) {
1052 client_id = silc_id_payload_get_id(idp);
1054 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1057 client = silc_idlist_find_client_by_id(server->global_list,
1063 client->data.public_key = public_key;
1064 } else if (id_type == SILC_ID_SERVER) {
1065 server_id = silc_id_payload_get_id(idp);
1067 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1069 if (!server_entry) {
1070 server_entry = silc_idlist_find_server_by_id(server->global_list,
1076 server_entry->data.public_key = public_key;
1082 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1083 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1085 silc_id_payload_free(idp);
1086 silc_free(client_id);
1087 silc_free(server_id);
1089 silc_pkcs_public_key_free(public_key);
1090 silc_server_command_reply_free(cmd);