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 */
97 silc_server_command_pending_check(server, ctx,
98 silc_command_get(ctx->payload),
99 ident, &ctx->callbacks_count);
101 /* Execute command reply */
102 command = silc_command_get(ctx->payload);
103 for (cmd = silc_command_reply_list; cmd->cb; cmd++)
104 if (cmd->cmd == command)
107 if (cmd == NULL || !cmd->cb) {
108 silc_server_command_reply_free(ctx);
115 /* Free command reply context and its internals. */
117 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
120 silc_command_payload_free(cmd->payload);
122 silc_socket_free(cmd->sock); /* Decrease the reference counter */
123 silc_free(cmd->callbacks);
128 /* Caches the received WHOIS information. */
131 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
133 SilcServer server = cmd->server;
134 unsigned char *tmp, *id_data;
135 char *nickname, *username, *realname, *servername = NULL;
136 SilcClientID *client_id;
137 SilcClientEntry client;
140 uint32 mode = 0, len, id_len;
142 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
143 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
144 username = silc_argument_get_arg_type(cmd->args, 4, &len);
145 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
146 if (!id_data || !nickname || !username || !realname) {
147 SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
148 nickname ? nickname : "",
149 username ? username : "",
150 realname ? realname : ""));
154 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
156 SILC_GET32_MSB(mode, tmp);
158 client_id = silc_id_payload_parse_id(id_data, id_len);
162 /* Check if we have this client cached already. */
164 client = silc_idlist_find_client_by_id(server->local_list, client_id,
167 client = silc_idlist_find_client_by_id(server->global_list, client_id,
173 /* If router did not find such Client ID in its lists then this must
174 be bogus client or some router in the net is buggy. */
175 if (server->server_type != SILC_SERVER)
178 /* Take hostname out of nick string if it includes it. */
179 silc_parse_userfqdn(nickname, &nick, &servername);
181 /* We don't have that client anywhere, add it. The client is added
182 to global list since server didn't have it in the lists so it must be
184 client = silc_idlist_add_client(server->global_list, nick,
186 strdup(realname), client_id,
187 cmd->sock->user_data, NULL);
189 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
193 client->data.status |=
194 (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
195 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
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 silc_parse_userfqdn(nickname, &nick, &servername);
206 /* Remove the old cache entry */
207 silc_idcache_del_by_context(global ? server->global_list->clients :
208 server->local_list->clients, client);
210 silc_free(client->nickname);
211 silc_free(client->username);
212 silc_free(client->userinfo);
213 silc_free(client->servername);
215 client->nickname = nick;
216 client->username = strdup(username);
217 client->userinfo = strdup(realname);
218 client->servername = servername;
220 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
221 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
223 /* Create new cache entry */
224 silc_idcache_add(global ? server->global_list->clients :
225 server->local_list->clients, nick, client->id,
227 silc_free(client_id);
233 /* Reiceved reply for WHOIS command. We sent the whois request to our
234 primary router, if we are normal server, and thus has now received reply
235 to the command. We will figure out what client originally sent us the
236 command and will send the reply to it. If we are router we will figure
237 out who server sent us the command and send reply to that one. */
239 SILC_SERVER_CMD_REPLY_FUNC(whois)
241 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
242 SilcCommandStatus status;
244 COMMAND_CHECK_STATUS_LIST;
246 if (!silc_server_command_reply_whois_save(cmd))
249 /* Pending callbacks are not executed if this was an list entry */
250 if (status != SILC_STATUS_OK &&
251 status != SILC_STATUS_LIST_END) {
252 silc_server_command_reply_free(cmd);
257 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
258 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
259 silc_server_command_reply_free(cmd);
262 /* Caches the received WHOWAS information for a short period of time. */
265 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
267 SilcServer server = cmd->server;
269 unsigned char *id_data;
270 char *nickname, *username, *realname, *servername = NULL;
271 SilcClientID *client_id;
272 SilcClientEntry client;
273 SilcIDCacheEntry cache = NULL;
277 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
278 nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
279 username = silc_argument_get_arg_type(cmd->args, 4, &len);
280 if (!id_data || !nickname || !username)
283 realname = silc_argument_get_arg_type(cmd->args, 5, &len);
285 client_id = silc_id_payload_parse_id(id_data, id_len);
289 /* Check if we have this client cached already. */
291 client = silc_idlist_find_client_by_id(server->local_list, client_id,
294 client = silc_idlist_find_client_by_id(server->global_list,
295 client_id, FALSE, &cache);
300 /* If router did not find such Client ID in its lists then this must
301 be bogus client or some router in the net is buggy. */
302 if (server->server_type != SILC_SERVER)
305 /* Take hostname out of nick string if it includes it. */
306 silc_parse_userfqdn(nickname, &nick, &servername);
308 /* We don't have that client anywhere, add it. The client is added
309 to global list since server didn't have it in the lists so it must be
311 client = silc_idlist_add_client(server->global_list, nick,
312 strdup(username), strdup(realname),
313 silc_id_dup(client_id, SILC_ID_CLIENT),
314 cmd->sock->user_data, NULL);
316 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
320 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
321 client = silc_idlist_find_client_by_id(server->global_list,
322 client_id, TRUE, &cache);
323 cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
324 client->servername = servername;
326 /* We have the client already, update the data */
328 /* Take hostname out of nick string if it includes it. */
329 silc_parse_userfqdn(nickname, &nick, &servername);
331 silc_free(client->nickname);
332 silc_free(client->username);
334 client->nickname = nick;
335 client->username = strdup(username);
336 client->servername = servername;
338 /* Remove the old cache entry and create a new one */
339 silc_idcache_del_by_context(global ? server->global_list->clients :
340 server->local_list->clients, client);
341 silc_idcache_add(global ? server->global_list->clients :
342 server->local_list->clients, nick, client->id,
346 silc_free(client_id);
351 /* Received reply for WHOWAS command. Cache the client information only for
352 a short period of time. */
354 SILC_SERVER_CMD_REPLY_FUNC(whowas)
356 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
357 SilcCommandStatus status;
359 COMMAND_CHECK_STATUS_LIST;
361 if (!silc_server_command_reply_whowas_save(cmd))
364 /* Pending callbacks are not executed if this was an list entry */
365 if (status != SILC_STATUS_OK &&
366 status != SILC_STATUS_LIST_END) {
367 silc_server_command_reply_free(cmd);
372 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
373 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
374 silc_server_command_reply_free(cmd);
377 /* Caches the received IDENTIFY information. */
380 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
382 SilcServer server = cmd->server;
384 unsigned char *id_data;
386 SilcClientID *client_id = NULL;
387 SilcServerID *server_id = NULL;
388 SilcChannelID *channel_id = NULL;
389 SilcClientEntry client;
390 SilcServerEntry server_entry;
391 SilcChannelEntry channel;
394 SilcIDPayload idp = NULL;
397 id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
400 idp = silc_id_payload_parse_data(id_data, id_len);
404 name = silc_argument_get_arg_type(cmd->args, 3, &len);
405 info = silc_argument_get_arg_type(cmd->args, 4, &len);
407 id_type = silc_id_payload_get_type(idp);
411 client_id = silc_id_payload_get_id(idp);
415 SILC_LOG_DEBUG(("Received client information"));
417 client = silc_idlist_find_client_by_id(server->local_list,
418 client_id, FALSE, NULL);
420 client = silc_idlist_find_client_by_id(server->global_list, client_id,
425 /* If router did not find such Client ID in its lists then this must
426 be bogus client or some router in the net is buggy. */
427 if (server->server_type != SILC_SERVER)
432 silc_parse_userfqdn(name, &nick, NULL);
434 /* We don't have that client anywhere, add it. The client is added
435 to global list since server didn't have it in the lists so it must be
437 client = silc_idlist_add_client(server->global_list, nick,
438 info ? strdup(info) : NULL, NULL,
439 client_id, cmd->sock->user_data, NULL);
441 SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
444 client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
445 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
446 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
448 /* We have the client already, update the data */
450 SILC_LOG_DEBUG(("Updating client data"));
454 silc_parse_userfqdn(name, &nick, NULL);
456 /* Remove the old cache entry */
457 silc_idcache_del_by_context(global ? server->global_list->clients :
458 server->local_list->clients, client);
460 silc_free(client->nickname);
461 client->nickname = nick;
465 silc_free(client->username);
466 client->username = strdup(info);
469 client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
470 client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
473 /* Add new cache entry */
474 silc_idcache_add(global ? server->global_list->clients :
475 server->local_list->clients, nick, client->id,
479 silc_free(client_id);
485 server_id = silc_id_payload_get_id(idp);
489 SILC_LOG_DEBUG(("Received server information"));
491 server_entry = silc_idlist_find_server_by_id(server->local_list,
492 server_id, FALSE, NULL);
494 server_entry = silc_idlist_find_server_by_id(server->global_list,
495 server_id, FALSE, NULL);
497 /* If router did not find such Server ID in its lists then this must
498 be bogus server or some router in the net is buggy. */
499 if (server->server_type != SILC_SERVER)
502 /* We don't have that server anywhere, add it. */
503 server_entry = silc_idlist_add_server(server->global_list,
505 server_id, NULL, NULL);
507 silc_free(server_id);
510 server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
511 server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
512 server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
516 silc_free(server_id);
519 case SILC_ID_CHANNEL:
520 channel_id = silc_id_payload_get_id(idp);
524 SILC_LOG_DEBUG(("Received channel information"));
526 channel = silc_idlist_find_channel_by_id(server->local_list,
529 channel = silc_idlist_find_channel_by_id(server->global_list, channel_id,
532 /* If router did not find such Channel ID in its lists then this must
533 be bogus channel or some router in the net is buggy. */
534 if (server->server_type != SILC_SERVER)
537 /* We don't have that server anywhere, add it. */
538 channel = silc_idlist_add_channel(server->global_list, strdup(name),
539 SILC_CHANNEL_MODE_NONE, channel_id,
540 server->router->connection,
543 silc_free(channel_id);
549 silc_free(channel_id);
553 silc_id_payload_free(idp);
557 silc_id_payload_free(idp);
561 /* Received reply for forwarded IDENTIFY command. We have received the
562 requested identify information now and we will cache it. After this we
563 will call the pending command so that the requestee gets the information
566 SILC_SERVER_CMD_REPLY_FUNC(identify)
568 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
569 SilcCommandStatus status;
571 COMMAND_CHECK_STATUS_LIST;
573 if (!silc_server_command_reply_identify_save(cmd))
576 /* Pending callbacks are not executed if this was an list entry */
577 if (status != SILC_STATUS_OK &&
578 status != SILC_STATUS_LIST_END) {
579 silc_server_command_reply_free(cmd);
584 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
585 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
586 silc_server_command_reply_free(cmd);
589 /* Received reply fro INFO command. Cache the server and its information */
591 SILC_SERVER_CMD_REPLY_FUNC(info)
593 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
594 SilcServer server = cmd->server;
595 SilcCommandStatus status;
596 SilcServerEntry entry;
597 SilcServerID *server_id;
599 unsigned char *tmp, *name;
601 COMMAND_CHECK_STATUS;
604 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
607 server_id = silc_id_payload_parse_id(tmp, tmp_len);
612 name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
616 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
619 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
622 /* Add the server to global list */
623 server_id = silc_id_dup(server_id, SILC_ID_SERVER);
624 entry = silc_idlist_add_server(server->global_list, name, 0,
625 server_id, NULL, NULL);
627 silc_free(server_id);
630 entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
634 /* Get the info string */
635 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
639 entry->server_info = tmp ? strdup(tmp) : NULL;
642 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
643 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
644 silc_server_command_reply_free(cmd);
647 /* Received reply fro MOTD command. */
649 SILC_SERVER_CMD_REPLY_FUNC(motd)
651 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
652 SilcServer server = cmd->server;
653 SilcCommandStatus status;
654 SilcServerEntry entry = NULL;
655 SilcServerID *server_id;
659 COMMAND_CHECK_STATUS;
662 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
665 server_id = silc_id_payload_parse_id(tmp, tmp_len);
669 entry = silc_idlist_find_server_by_id(server->local_list, server_id,
672 entry = silc_idlist_find_server_by_id(server->global_list, server_id,
679 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
686 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
687 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
688 silc_server_command_reply_free(cmd);
694 /* Received reply for forwarded JOIN command. Router has created or joined
695 the client to the channel. We save some channel information locally
698 SILC_SERVER_CMD_REPLY_FUNC(join)
700 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
701 SilcServer server = cmd->server;
702 SilcIDCacheEntry cache = NULL;
703 SilcCommandStatus status;
705 SilcClientID *client_id = NULL;
706 SilcChannelEntry entry;
707 SilcHmac hmac = NULL;
708 uint32 id_len, len, list_count;
709 unsigned char *id_string;
710 char *channel_name, *tmp;
711 uint32 mode, created;
712 SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
714 COMMAND_CHECK_STATUS;
716 /* Get channel name */
717 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
722 id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
727 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
730 client_id = silc_id_payload_parse_id(tmp, len);
735 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
738 SILC_GET32_MSB(mode, tmp);
740 /* Get created boolean value */
741 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
744 SILC_GET32_MSB(created, tmp);
745 if (created != 0 && created != 1)
748 /* Get channel key */
749 tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
751 keyp = silc_buffer_alloc(len);
752 silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
753 silc_buffer_put(keyp, tmp, len);
756 id = silc_id_payload_parse_id(id_string, id_len);
761 tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
763 if (!silc_hmac_alloc(tmp, NULL, &hmac))
767 /* Get the list count */
768 tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
771 SILC_GET32_MSB(list_count, tmp);
773 /* Get Client ID list */
774 tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
778 client_id_list = silc_buffer_alloc(len);
779 silc_buffer_pull_tail(client_id_list, len);
780 silc_buffer_put(client_id_list, tmp, len);
782 /* Get client mode list */
783 tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
787 client_mode_list = silc_buffer_alloc(len);
788 silc_buffer_pull_tail(client_mode_list, len);
789 silc_buffer_put(client_mode_list, tmp, len);
791 /* See whether we already have the channel. */
792 entry = silc_idlist_find_channel_by_name(server->local_list,
793 channel_name, &cache);
795 /* Add new channel */
797 SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
798 (created == 0 ? "existing" : "created"), channel_name,
799 silc_id_render(id, SILC_ID_CHANNEL)));
801 /* If the channel is found from global list we must move it to the
803 entry = silc_idlist_find_channel_by_name(server->global_list,
804 channel_name, &cache);
806 silc_idlist_del_channel(server->global_list, entry);
808 /* Add the channel to our local list. */
809 entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
810 SILC_CHANNEL_MODE_NONE, id,
811 server->router, NULL, hmac);
816 server->stat.my_channels++;
818 /* The entry exists. */
820 silc_free(cache->id);
822 cache->id = entry->id;
824 /* Remove the founder auth data if the mode is not set but we have
826 if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
827 silc_pkcs_public_key_free(entry->founder_key);
828 if (entry->founder_passwd) {
829 silc_free(entry->founder_passwd);
830 entry->founder_passwd = NULL;
835 if (entry->hmac_name && hmac) {
836 silc_free(entry->hmac_name);
837 entry->hmac_name = strdup(silc_hmac_get_name(hmac));
840 /* Get the ban list */
841 tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
844 silc_free(entry->ban_list);
845 entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
846 memcpy(entry->ban_list, tmp, len);
849 /* Get the invite list */
850 tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
852 if (entry->invite_list)
853 silc_free(entry->invite_list);
854 entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
855 memcpy(entry->invite_list, tmp, len);
859 tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
862 silc_free(entry->topic);
863 entry->topic = strdup(tmp);
866 /* If channel was not created we know there is global users on the
868 entry->global_users = (created == 0 ? TRUE : FALSE);
870 /* If channel was just created the mask must be zero */
871 if (!entry->global_users && mode) {
872 SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
873 "new channel, forcing it to zero", cmd->sock->hostname));
877 /* Save channel mode */
880 /* Save channel key */
881 if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
882 silc_server_save_channel_key(server, keyp, entry);
884 silc_buffer_free(keyp);
886 /* Save the users to the channel */
887 silc_server_save_users_on_channel(server, cmd->sock, entry,
888 client_id, client_id_list,
889 client_mode_list, list_count);
892 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
893 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
894 silc_free(client_id);
895 silc_server_command_reply_free(cmd);
898 silc_buffer_free(client_id_list);
899 if (client_mode_list)
900 silc_buffer_free(client_mode_list);
903 SILC_SERVER_CMD_REPLY_FUNC(users)
905 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
906 SilcServer server = cmd->server;
907 SilcCommandStatus status;
908 SilcChannelEntry channel;
909 SilcChannelID *channel_id = NULL;
910 SilcBuffer client_id_list;
911 SilcBuffer client_mode_list;
916 COMMAND_CHECK_STATUS;
919 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
922 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
926 /* Get channel entry */
927 channel = silc_idlist_find_channel_by_id(server->local_list,
930 channel = silc_idlist_find_channel_by_id(server->global_list,
935 if (server->server_type != SILC_SERVER)
938 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
939 silc_server_send_command(server, server->router->connection,
940 SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
941 1, 5, idp->data, idp->len);
942 silc_buffer_free(idp);
944 /* Register pending command callback. After we've received the channel
945 information we will reprocess this command reply by re-calling this
946 USERS command reply callback. */
947 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
949 NULL, silc_server_command_reply_users, cmd);
954 /* Get the list count */
955 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
958 SILC_GET32_MSB(list_count, tmp);
960 /* Get Client ID list */
961 tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
965 client_id_list = silc_buffer_alloc(tmp_len);
966 silc_buffer_pull_tail(client_id_list, tmp_len);
967 silc_buffer_put(client_id_list, tmp, tmp_len);
969 /* Get client mode list */
970 tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
974 client_mode_list = silc_buffer_alloc(tmp_len);
975 silc_buffer_pull_tail(client_mode_list, tmp_len);
976 silc_buffer_put(client_mode_list, tmp, tmp_len);
978 /* Save the users to the channel */
979 silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
980 client_id_list, client_mode_list,
983 silc_buffer_free(client_id_list);
984 silc_buffer_free(client_mode_list);
987 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
988 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
989 silc_free(channel_id);
990 silc_server_command_reply_free(cmd);
993 SILC_SERVER_CMD_REPLY_FUNC(getkey)
995 SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
996 SilcServer server = cmd->server;
997 SilcCommandStatus status;
998 SilcClientEntry client = NULL;
999 SilcServerEntry server_entry = NULL;
1000 SilcClientID *client_id = NULL;
1001 SilcServerID *server_id = NULL;
1003 unsigned char *tmp, *pk;
1006 SilcIDPayload idp = NULL;
1008 SilcPublicKey public_key = NULL;
1010 COMMAND_CHECK_STATUS;
1012 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1015 idp = silc_id_payload_parse_data(tmp, len);
1019 /* Get the public key payload */
1020 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1024 /* Decode the public key */
1026 SILC_GET16_MSB(pk_len, tmp);
1027 SILC_GET16_MSB(type, tmp + 2);
1030 if (type != SILC_SKE_PK_TYPE_SILC)
1033 if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
1036 id_type = silc_id_payload_get_type(idp);
1037 if (id_type == SILC_ID_CLIENT) {
1038 client_id = silc_id_payload_get_id(idp);
1040 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1043 client = silc_idlist_find_client_by_id(server->global_list,
1044 client_id, TRUE, NULL);
1049 client->data.public_key = public_key;
1050 } else if (id_type == SILC_ID_SERVER) {
1051 server_id = silc_id_payload_get_id(idp);
1053 server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1055 if (!server_entry) {
1056 server_entry = silc_idlist_find_server_by_id(server->global_list,
1057 server_id, TRUE, NULL);
1062 server_entry->data.public_key = public_key;
1068 SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1069 SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
1071 silc_id_payload_free(idp);
1072 silc_free(client_id);
1073 silc_free(server_id);
1075 silc_pkcs_public_key_free(public_key);
1076 silc_server_command_reply_free(cmd);