Static analyzer bug fixes
[silc.git] / apps / silcd / command_reply.c
1 /*
2
3   command_reply.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2009 Pekka Riikonen
8
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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
24
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26    out: and err: goto labels. */
27
28 #define COMMAND_CHECK_STATUS                                            \
29 do {                                                                    \
30   SILC_LOG_DEBUG(("Start"));                                            \
31   if (!silc_command_get_status(cmd->payload, &status, &error)) {        \
32     if (SILC_STATUS_IS_ERROR(status))                                   \
33       goto out;                                                         \
34     if (status == SILC_STATUS_LIST_END)                                 \
35       goto out;                                                         \
36     goto err;                                                           \
37   }                                                                     \
38 } while(0)
39
40 /* Server command reply list. Not all commands have reply function as
41    they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
43 {
44   SILC_SERVER_CMD_REPLY(whois, WHOIS),
45   SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46   SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47   SILC_SERVER_CMD_REPLY(info, INFO),
48   SILC_SERVER_CMD_REPLY(motd, MOTD),
49   SILC_SERVER_CMD_REPLY(join, JOIN),
50   SILC_SERVER_CMD_REPLY(stats, STATS),
51   SILC_SERVER_CMD_REPLY(users, USERS),
52   SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53   SILC_SERVER_CMD_REPLY(list, LIST),
54   SILC_SERVER_CMD_REPLY(watch, WATCH),
55   SILC_SERVER_CMD_REPLY(ping, PING),
56
57   { NULL, 0 },
58 };
59
60 /* Process received command reply. */
61
62 void silc_server_command_reply_process(SilcServer server,
63                                        SilcPacketStream sock,
64                                        SilcBuffer buffer)
65 {
66   SilcIDListData idata = silc_packet_get_context(sock);
67   SilcServerCommandReply *cmd;
68   SilcServerCommandReplyContext ctx;
69   SilcCommandPayload payload;
70   SilcCommand command;
71
72   SILC_LOG_DEBUG(("Start"));
73
74   /* Get command reply payload from packet */
75   payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
76   if (!payload) {
77     /* Silently ignore bad reply packet */
78     SILC_LOG_DEBUG(("Bad command reply packet"));
79     return;
80   }
81
82   /* Allocate command reply context. This must be free'd by the
83      command reply routine receiving it. */
84   ctx = silc_calloc(1, sizeof(*ctx));
85   ctx->server = server;
86   ctx->sock = sock;
87   ctx->payload = payload;
88   ctx->args = silc_command_get_args(ctx->payload);
89   ctx->ident = silc_command_get_ident(ctx->payload);
90   command = silc_command_get(ctx->payload);
91   silc_packet_stream_ref(sock);
92
93   /* Client is not allowed to send reply to all commands */
94   if (idata->conn_type == SILC_CONN_CLIENT &&
95       command != SILC_COMMAND_WHOIS) {
96     silc_server_command_reply_free(ctx);
97     return;
98   }
99
100   /* Check for pending commands and mark to be exeucted */
101   ctx->callbacks =
102     silc_server_command_pending_check(server, command,
103                                       ctx->ident, &ctx->callbacks_count);
104
105   /* Execute command reply */
106   for (cmd = silc_command_reply_list; cmd->cb; cmd++)
107     if (cmd->cmd == command)
108       break;
109
110   if (cmd == NULL || !cmd->cb) {
111     silc_server_command_reply_free(ctx);
112     return;
113   }
114
115   cmd->cb(ctx, NULL);
116 }
117
118 /* Free command reply context and its internals. */
119
120 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
121 {
122   if (cmd) {
123     silc_command_payload_free(cmd->payload);
124     if (cmd->sock)
125       silc_packet_stream_unref(cmd->sock);
126     silc_free(cmd->callbacks);
127     silc_free(cmd);
128   }
129 }
130
131 static void
132 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
133                                   SilcStatus error)
134 {
135   SilcServer server = cmd->server;
136   SilcIDListData idata = silc_packet_get_context(cmd->sock);
137
138   /* If we received notify for invalid ID we'll remove the ID if we
139      have it cached. */
140   if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
141       idata->conn_type == SILC_CONN_ROUTER) {
142     SilcClientEntry client;
143     SilcID id;
144     if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
145                                   NULL)) {
146       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
147                       "the entry from cache"));
148       client = silc_idlist_find_client_by_id(server->global_list,
149                                              SILC_ID_GET_ID(id), FALSE, NULL);
150       if (!client)
151         return;
152
153       silc_server_remove_from_channels(server, NULL, client, TRUE,
154                                        NULL, TRUE, FALSE);
155       silc_dlist_del(server->expired_clients, client);
156       silc_idlist_del_data(client);
157       silc_idlist_del_client(server->global_list, client);
158     }
159   }
160 }
161
162 /* Caches the received WHOIS information. */
163
164 static char
165 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
166 {
167   SilcServer server = cmd->server;
168   unsigned char *id_data, *umodes;
169   char *nickname, *username, *realname, *tmp;
170   unsigned char *fingerprint;
171   SilcID id;
172   SilcClientEntry client;
173   char global = FALSE;
174   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
175   SilcUInt32 mode = 0, len, len2, id_len, flen;
176   const char *hostname, *ip;
177
178   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
179                               NULL, &hostname, &ip, NULL);
180
181   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
182   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
183   username = silc_argument_get_arg_type(cmd->args, 4, &len);
184   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
185   if (!id_data || !nickname || !username || !realname)
186     return FALSE;
187
188   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
189   if (tmp)
190     SILC_GET32_MSB(mode, tmp);
191
192   if (!silc_id_payload_parse_id(id_data, id_len, &id))
193     return FALSE;
194
195   fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
196
197   /* Check if we have this client cached already. */
198
199   client = silc_idlist_find_client_by_id(server->local_list,
200                                          SILC_ID_GET_ID(id),
201                                          FALSE, NULL);
202   if (!client) {
203     client = silc_idlist_find_client_by_id(server->global_list,
204                                            SILC_ID_GET_ID(id),
205                                            FALSE, NULL);
206     global = TRUE;
207   }
208
209   if (!client) {
210     /* If router did not find such Client ID in its lists then this must
211        be bogus client or some router in the net is buggy. */
212     if (server->server_type != SILC_SERVER)
213       return FALSE;
214
215     /* Take hostname out of nick string if it includes it. */
216     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
217                         sizeof(servername));
218
219     /* We don't have that client anywhere, add it. The client is added
220        to global list since server didn't have it in the lists so it must be
221        global. This will check for valid nickname and username strings. */
222     client = silc_idlist_add_client(server->global_list,
223                                     strdup(nick), username,
224                                     strdup(realname),
225                                     silc_id_dup(SILC_ID_GET_ID(id),
226                                                 SILC_ID_CLIENT),
227                                     silc_packet_get_context(cmd->sock),
228                                     NULL);
229     if (!client) {
230       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
231       return FALSE;
232     }
233
234     client->data.status |=
235       (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
236     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
237     client->mode = mode;
238     client->servername = servername[0] ? strdup(servername) : NULL;
239
240     SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
241                     server->stat.clients + 1));
242     server->stat.clients++;
243   } else {
244     /* We have the client already, update the data */
245
246     SILC_LOG_DEBUG(("Updating client data"));
247
248     /* Check nickname */
249     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
250                         sizeof(servername));
251     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
252                                      128, NULL);
253     if (!nickname) {
254       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
255                       "from %s",
256                       hostname ? hostname : "", nick));
257       return FALSE;
258     }
259
260     /* Check username */
261     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
262     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
263       SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
264                       "from %s",
265                       hostname ? hostname : "", tmp));
266       return FALSE;
267     }
268
269     /* Update entry */
270     silc_idcache_update_by_context(global ? server->global_list->clients :
271                                    server->local_list->clients, client, NULL,
272                                    nickname, TRUE);
273
274     silc_free(client->nickname);
275     silc_free(client->username);
276     silc_free(client->userinfo);
277     silc_free(client->servername);
278
279     client->nickname = strdup(nick);
280     client->username = strdup(username);
281     client->userinfo = strdup(realname);
282     client->servername = servername[0] ? strdup(servername) : NULL;
283     client->mode = mode;
284     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
285     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
286   }
287
288   /* Save channel list if it was sent to us */
289   if (server->server_type == SILC_SERVER) {
290     tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
291     umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
292     if (tmp && umodes) {
293       SilcBufferStruct channels_buf, umodes_buf;
294       silc_buffer_set(&channels_buf, tmp, len);
295       silc_buffer_set(&umodes_buf, umodes, len2);
296       silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
297                                      &umodes_buf);
298     } else {
299       silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
300     }
301   }
302
303   if (fingerprint && flen == sizeof(client->data.fingerprint))
304     memcpy(client->data.fingerprint, fingerprint, flen);
305
306   /* Take Requested Attributes if set. */
307   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
308   if (tmp) {
309     silc_free(client->attrs);
310     client->attrs = silc_memdup(tmp, len);
311     client->attrs_len = len;
312
313     /* Try to take public key from attributes if present and we don't have
314        the key already.  Do this only on normal server.  Routers do GETKEY
315        for all clients anyway. */
316     if (server->server_type != SILC_ROUTER && !client->data.public_key) {
317       SilcAttributePayload attr;
318       SilcAttributeObjPk pk;
319       unsigned char f[SILC_HASH_MAXLEN];
320       SilcDList attrs = silc_attribute_payload_parse(tmp, len);
321
322       SILC_LOG_DEBUG(("Take client public key from attributes"));
323
324       if (attrs) {
325         silc_dlist_start(attrs);
326         while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
327           if (silc_attribute_get_attribute(attr) ==
328               SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
329
330             if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
331               continue;
332
333             /* Take only SILC public keys */
334             if (strcmp(pk.type, "silc-rsa")) {
335               silc_free(pk.type);
336               silc_free(pk.data);
337               continue;
338             }
339
340             /* Verify that the server provided fingerprint matches the key */
341             silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
342             if (memcmp(f, client->data.fingerprint, sizeof(f))) {
343               silc_free(pk.type);
344               silc_free(pk.data);
345               continue;
346             }
347
348             /* Save the public key. */
349             if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
350                                             pk.data, pk.data_len,
351                                             &client->data.public_key)) {
352               silc_free(pk.type);
353               silc_free(pk.data);
354               continue;
355             }
356
357             SILC_LOG_DEBUG(("Saved client public key from attributes"));
358
359             /* Add client's public key to repository */
360             if (!silc_server_get_public_key_by_client(server, client, NULL))
361               silc_skr_add_public_key_simple(server->repository,
362                                              client->data.public_key,
363                                              SILC_SKR_USAGE_IDENTIFICATION,
364                                              client, NULL);
365
366             silc_free(pk.type);
367             silc_free(pk.data);
368             break;
369           }
370         }
371
372         silc_attribute_payload_list_free(attrs);
373       }
374     }
375   }
376
377   return TRUE;
378 }
379
380 /* Handle requested attributes reply in WHOIS from client */
381
382 static char
383 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
384 {
385   unsigned char *tmp;
386   SilcUInt32 len;
387   SilcClientEntry client = silc_packet_get_context(cmd->sock);
388
389   if (!client)
390     return FALSE;
391
392   /* Take Requested Attributes if set. */
393   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
394   if (tmp) {
395     silc_free(client->attrs);
396     client->attrs = silc_memdup(tmp, len);
397     client->attrs_len = len;
398   }
399
400   client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
401
402   return TRUE;
403 }
404
405 /* Reiceved reply for WHOIS command. We sent the whois request to our
406    primary router, if we are normal server, and thus has now received reply
407    to the command. We will figure out what client originally sent us the
408    command and will send the reply to it.  If we are router we will figure
409    out who server sent us the command and send reply to that one. */
410
411 SILC_SERVER_CMD_REPLY_FUNC(whois)
412 {
413   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
414   SilcIDListData idata = silc_packet_get_context(cmd->sock);
415   SilcStatus status, error;
416
417   COMMAND_CHECK_STATUS;
418
419   if (idata->conn_type != SILC_CONN_CLIENT) {
420     if (!silc_server_command_reply_whois_save(cmd))
421       goto out;
422   } else {
423     if (!silc_server_command_reply_whois_save_client(cmd))
424       goto out;
425   }
426
427   /* Pending callbacks are not executed if this was an list entry */
428   if (status != SILC_STATUS_OK &&
429       status != SILC_STATUS_LIST_END) {
430     silc_server_command_reply_free(cmd);
431     return;
432   }
433
434  out:
435   silc_server_command_process_error(cmd, error);
436   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
437   silc_server_command_reply_free(cmd);
438   return;
439
440  err:
441   silc_server_command_process_error(cmd, error);
442   silc_server_command_reply_free(cmd);
443 }
444
445 /* Caches the received WHOWAS information for a short period of time. */
446
447 static char
448 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
449 {
450   SilcServer server = cmd->server;
451   SilcUInt32 len, id_len;
452   unsigned char *id_data;
453   char *nickname, *username, *realname;
454   SilcID id;
455   SilcClientEntry client;
456   SilcIDCacheEntry cache = NULL;
457   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
458   int global = FALSE;
459   const char *hostname, *ip;
460
461   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
462                               NULL, &hostname, &ip, NULL);
463
464   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
465   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
466   username = silc_argument_get_arg_type(cmd->args, 4, &len);
467   if (!id_data || !nickname || !username)
468     return FALSE;
469
470   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
471
472   if (!silc_id_payload_parse_id(id_data, id_len, &id))
473     return FALSE;
474
475   /* Check if we have this client cached already. */
476
477   client = silc_idlist_find_client_by_id(server->local_list,
478                                          SILC_ID_GET_ID(id),
479                                          FALSE, &cache);
480   if (!client) {
481     client = silc_idlist_find_client_by_id(server->global_list,
482                                            SILC_ID_GET_ID(id),
483                                            FALSE, &cache);
484     global = TRUE;
485   }
486
487   if (!client) {
488     /* If router did not find such Client ID in its lists then this must
489        be bogus client or some router in the net is buggy. */
490     if (server->server_type != SILC_SERVER)
491       return FALSE;
492
493     /* Take hostname out of nick string if it includes it. */
494     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
495                         sizeof(servername));
496
497     /* We don't have that client anywhere, add it. The client is added
498        to global list since server didn't have it in the lists so it must be
499        global. */
500     client = silc_idlist_add_client(server->global_list,
501                                     strdup(nick), username,
502                                     strdup(realname),
503                                     silc_id_dup(SILC_ID_GET_ID(id),
504                                                 SILC_ID_CLIENT),
505                                     silc_packet_get_context(cmd->sock), NULL);
506     if (!client) {
507       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
508       return FALSE;
509     }
510
511     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
512     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
513     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
514     client->servername = servername[0] ? strdup(servername) : NULL;
515   } else {
516     /* We have the client already, update the data */
517
518     /* Check nickname */
519     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
520                         sizeof(servername));
521     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
522                                      128, NULL);
523     if (!nickname) {
524       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
525                       "from %s",
526                       nick, hostname ? hostname : ""));
527       return FALSE;
528     }
529
530     /* Check username */
531     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
532     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
533       return FALSE;
534
535     silc_free(client->nickname);
536     silc_free(client->username);
537     silc_free(client->servername);
538
539     client->nickname = strdup(nick);
540     client->username = strdup(username);
541     client->servername = servername[0] ? strdup(servername) : NULL;
542     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
543     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
544     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
545
546     /* Update cache entry */
547     silc_idcache_update_by_context(global ? server->global_list->clients :
548                                    server->local_list->clients, client, NULL,
549                                    nickname, TRUE);
550   }
551
552   /* If client is global and is not on any channel then add that we'll
553      expire the entry after a while. */
554   if (global) {
555     client = silc_idlist_find_client_by_id(server->global_list, client->id,
556                                            FALSE, &cache);
557     if (client && !silc_hash_table_count(client->channels)) {
558       client->data.created = silc_time();
559       silc_dlist_del(server->expired_clients, client);
560       silc_dlist_add(server->expired_clients, client);
561     }
562   }
563
564   return TRUE;
565 }
566
567 /* Received reply for WHOWAS command. Cache the client information only for
568    a short period of time. */
569
570 SILC_SERVER_CMD_REPLY_FUNC(whowas)
571 {
572   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
573   SilcStatus status, error;
574
575   COMMAND_CHECK_STATUS;
576
577   if (!silc_server_command_reply_whowas_save(cmd))
578     goto out;
579
580   /* Pending callbacks are not executed if this was an list entry */
581   if (status != SILC_STATUS_OK &&
582       status != SILC_STATUS_LIST_END) {
583     silc_server_command_reply_free(cmd);
584     return;
585   }
586
587  out:
588   silc_server_command_process_error(cmd, error);
589   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
590   silc_server_command_reply_free(cmd);
591   return;
592
593  err:
594   silc_server_command_process_error(cmd, error);
595   silc_server_command_reply_free(cmd);
596 }
597
598 /* Caches the received IDENTIFY information. */
599
600 static char
601 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
602 {
603   SilcServer server = cmd->server;
604   SilcUInt32 len, id_len;
605   unsigned char *id_data;
606   char *name, *info;
607   SilcClientID client_id;
608   SilcServerID server_id;
609   SilcChannelID channel_id;
610   SilcClientEntry client;
611   SilcServerEntry server_entry;
612   SilcChannelEntry channel;
613   char global = FALSE;
614   char nick[128 + 1];
615   SilcIDPayload idp = NULL;
616   SilcIdType id_type;
617
618   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
619   if (!id_data)
620     return FALSE;
621   idp = silc_id_payload_parse(id_data, id_len);
622   if (!idp)
623     return FALSE;
624
625   memset(nick, 0, sizeof(nick));
626
627   name = silc_argument_get_arg_type(cmd->args, 3, &len);
628   info = silc_argument_get_arg_type(cmd->args, 4, &len);
629
630   id_type = silc_id_payload_get_type(idp);
631
632   switch (id_type) {
633   case SILC_ID_CLIENT:
634     if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
635       goto error;
636
637     SILC_LOG_DEBUG(("Received client information"));
638
639     client = silc_idlist_find_client_by_id(server->local_list,
640                                            &client_id, FALSE, NULL);
641     if (!client) {
642       client = silc_idlist_find_client_by_id(server->global_list, &client_id,
643                                              FALSE, NULL);
644       global = TRUE;
645     }
646     if (!client) {
647       /* If router did not find such Client ID in its lists then this must
648          be bogus client or some router in the net is buggy. */
649       if (server->server_type != SILC_SERVER)
650         goto error;
651
652       /* Take nickname */
653       if (name)
654         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
655
656       /* We don't have that client anywhere, add it. The client is added
657          to global list since server didn't have it in the lists so it must be
658          global. */
659       client = silc_idlist_add_client(server->global_list,
660                                       nick[0] ? strdup(nick) : NULL,
661                                       info ? strdup(info) : NULL, NULL,
662                                       silc_id_dup(&client_id, SILC_ID_CLIENT),
663                                       silc_packet_get_context(cmd->sock),
664                                       NULL);
665       if (!client) {
666         SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
667         goto error;
668       }
669
670       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
671       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
672       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
673
674       SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
675                       server->stat.clients + 1));
676       server->stat.clients++;
677     } else {
678       /* We have the client already, update the data */
679
680       SILC_LOG_DEBUG(("Updating client data"));
681
682       /* Take nickname */
683       if (name) {
684         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
685
686         /* Check nickname */
687         name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
688                                      128, NULL);
689         if (!name) {
690           SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
691                           "reply ", nick));
692           return FALSE;
693         }
694
695         silc_free(client->nickname);
696         client->nickname = strdup(nick);
697
698         /* Update the context */
699         silc_idcache_update_by_context(global ? server->global_list->clients :
700                                        server->local_list->clients, client,
701                                        NULL, name, TRUE);
702       }
703
704       if (info) {
705         silc_free(client->username);
706         client->username = strdup(info);
707       }
708
709       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
710       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
711     }
712
713     break;
714
715   case SILC_ID_SERVER:
716     if (!name)
717       goto error;
718
719     if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
720       goto error;
721
722     SILC_LOG_DEBUG(("Received server information"));
723
724     server_entry = silc_idlist_find_server_by_id(server->local_list,
725                                                  &server_id, FALSE, NULL);
726     if (!server_entry)
727       server_entry = silc_idlist_find_server_by_id(server->global_list,
728                                                    &server_id, FALSE, NULL);
729     if (!server_entry) {
730       /* If router did not find such Server ID in its lists then this must
731          be bogus server or some router in the net is buggy. */
732       if (server->server_type != SILC_SERVER)
733         goto error;
734
735       /* We don't have that server anywhere, add it. */
736       server_entry = silc_idlist_add_server(server->global_list,
737                                             strdup(name), 0,
738                                             silc_id_dup(&server_id,
739                                                         SILC_ID_SERVER),
740                                             server->router,
741                                             SILC_PRIMARY_ROUTE(server));
742       if (!server_entry)
743         goto error;
744
745       server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
746       server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
747       server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
748     }
749
750     break;
751
752   case SILC_ID_CHANNEL:
753     if (!name)
754       goto error;
755
756     if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
757       goto error;
758
759     SILC_LOG_DEBUG(("Received channel information"));
760
761     /* Check channel name */
762     info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
763                                    256, NULL);
764     if (!info)
765       goto error;
766
767     channel = silc_idlist_find_channel_by_name(server->local_list,
768                                                info, NULL);
769     if (!channel)
770       channel = silc_idlist_find_channel_by_name(server->global_list,
771                                                  info, NULL);
772     if (!channel) {
773       /* If router did not find such Channel ID in its lists then this must
774          be bogus channel or some router in the net is buggy. */
775       if (server->server_type != SILC_SERVER) {
776         silc_free(info);
777         goto error;
778       }
779
780       /* We don't have that channel anywhere, add it. */
781       channel = silc_idlist_add_channel(server->global_list, strdup(name),
782                                         SILC_CHANNEL_MODE_NONE,
783                                         silc_id_dup(&channel_id,
784                                                     SILC_ID_CHANNEL),
785                                         server->router, NULL, NULL, 0);
786       if (!channel) {
787         silc_free(info);
788         goto error;
789       }
790       silc_free(info);
791     }
792
793     break;
794   }
795
796   silc_id_payload_free(idp);
797   return TRUE;
798
799  error:
800   silc_id_payload_free(idp);
801   return FALSE;
802 }
803
804 /* Received reply for forwarded IDENTIFY command. We have received the
805    requested identify information now and we will cache it. After this we
806    will call the pending command so that the requestee gets the information
807    after all. */
808
809 SILC_SERVER_CMD_REPLY_FUNC(identify)
810 {
811   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
812   SilcStatus status, error;
813
814   COMMAND_CHECK_STATUS;
815
816   if (!silc_server_command_reply_identify_save(cmd))
817     goto out;
818
819   /* Pending callbacks are not executed if this was an list entry */
820   if (status != SILC_STATUS_OK &&
821       status != SILC_STATUS_LIST_END) {
822     silc_server_command_reply_free(cmd);
823     return;
824   }
825
826  out:
827   silc_server_command_process_error(cmd, error);
828   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
829   silc_server_command_reply_free(cmd);
830   return;
831
832  err:
833   silc_server_command_process_error(cmd, error);
834   silc_server_command_reply_free(cmd);
835 }
836
837 /* Received reply fro INFO command. Cache the server and its information */
838
839 SILC_SERVER_CMD_REPLY_FUNC(info)
840 {
841   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
842   SilcServer server = cmd->server;
843   SilcStatus status, error;
844   SilcServerEntry entry;
845   SilcID id;
846   SilcUInt32 tmp_len;
847   unsigned char *tmp, *name;
848
849   COMMAND_CHECK_STATUS;
850
851   /* Get Server ID */
852   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
853     goto out;
854
855   /* Get the name */
856   name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
857   if (!name)
858     goto out;
859
860   entry = silc_idlist_find_server_by_id(server->local_list,
861                                         SILC_ID_GET_ID(id),
862                                         FALSE, NULL);
863   if (!entry) {
864     entry = silc_idlist_find_server_by_id(server->global_list,
865                                           SILC_ID_GET_ID(id),
866                                           FALSE, NULL);
867     if (!entry) {
868       /* Add the server to global list */
869       entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
870                                      silc_id_dup(SILC_ID_GET_ID(id),
871                                                  SILC_ID_SERVER),
872                                      silc_packet_get_context(cmd->sock),
873                                      cmd->sock);
874       if (!entry)
875         goto out;
876
877       entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
878     }
879   }
880
881   /* Get the info string */
882   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
883   if (tmp_len > 256)
884     tmp = NULL;
885
886   entry->server_info = tmp ? strdup(tmp) : NULL;
887
888  out:
889   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
890  err:
891   silc_server_command_reply_free(cmd);
892 }
893
894 /* Received reply fro MOTD command. */
895
896 SILC_SERVER_CMD_REPLY_FUNC(motd)
897 {
898   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
899   SilcServer server = cmd->server;
900   SilcStatus status, error;
901   SilcServerEntry entry = NULL;
902   SilcID id;
903   SilcUInt32 tmp_len;
904   unsigned char *tmp;
905
906   COMMAND_CHECK_STATUS;
907
908   /* Get Server ID */
909   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
910     goto out;
911
912   entry = silc_idlist_find_server_by_id(server->local_list,
913                                         SILC_ID_GET_ID(id),
914                                         TRUE, NULL);
915   if (!entry) {
916     entry = silc_idlist_find_server_by_id(server->global_list,
917                                           SILC_ID_GET_ID(id),
918                                           TRUE, NULL);
919     if (!entry) {
920       SilcBuffer buffer;
921
922       /* If router did not find such Server ID in its lists then this must
923          be bogus client or some router in the net is buggy. */
924       if (server->server_type != SILC_SERVER)
925         goto out;
926
927       /* Statistics */
928       cmd->server->stat.commands_sent++;
929
930       /* entry isn't known so we IDENTIFY it. otherwise the
931          silc_server_command_motd won't know about it and tell
932          the client that there is no such server */
933       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
934       buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
935                                               ++server->cmd_ident, 5,
936                                               1, NULL, 0, 2, NULL, 0,
937                                               3, NULL, 0, 4, NULL, 0,
938                                               5, tmp, tmp_len);
939       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
940                               SILC_PACKET_COMMAND, 0, buffer->data,
941                               silc_buffer_len(buffer));
942       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
943                                   server->cmd_ident,
944                                   silc_server_command_reply_motd,
945                                   cmd);
946       silc_buffer_free(buffer);
947       return;
948     }
949   }
950
951   /* Get the motd */
952   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
953   if (tmp_len > 256)
954     tmp = NULL;
955
956   entry->motd = tmp;
957
958  out:
959   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
960  err:
961   silc_server_command_reply_free(cmd);
962
963   if (entry)
964     entry->motd = NULL;
965 }
966
967 /* Received reply for forwarded JOIN command. Router has created or joined
968    the client to the channel. We save some channel information locally
969    for future use. */
970
971 SILC_SERVER_CMD_REPLY_FUNC(join)
972 {
973   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
974   SilcServer server = cmd->server;
975   SilcIDCacheEntry cache = NULL;
976   SilcStatus status, error;
977   SilcID id, id2;
978   SilcChannelEntry entry;
979   SilcHmac hmac = NULL;
980   SilcUInt32 len, list_count;
981   char *channel_name, *channel_namec = NULL, *tmp;
982   SilcUInt32 mode, created;
983   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
984   SilcPublicKey founder_key = NULL;
985
986   COMMAND_CHECK_STATUS;
987
988   /* Get channel name */
989   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
990   if (!channel_name)
991     goto out;
992
993   /* Get channel ID */
994   if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
995     goto out;
996
997   /* Get client ID */
998   if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
999     goto out;
1000
1001   /* Get mode mask */
1002   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1003   if (!tmp)
1004     goto out;
1005   SILC_GET32_MSB(mode, tmp);
1006
1007   /* Get created boolean value */
1008   tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1009   if (!tmp)
1010     goto out;
1011   SILC_GET32_MSB(created, tmp);
1012   if (created != 0 && created != 1)
1013     goto out;
1014
1015   /* Get channel key */
1016   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1017   if (tmp) {
1018     keyp = silc_buffer_alloc(len);
1019     silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1020     silc_buffer_put(keyp, tmp, len);
1021   }
1022
1023   /* Get hmac */
1024   tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1025   if (tmp) {
1026     if (!silc_hmac_alloc(tmp, NULL, &hmac))
1027       goto out;
1028   }
1029
1030   /* Get the list count */
1031   tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1032   if (!tmp)
1033     goto out;
1034   SILC_GET32_MSB(list_count, tmp);
1035
1036   /* Get Client ID list */
1037   tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1038   if (!tmp)
1039     goto out;
1040
1041   client_id_list = silc_buffer_alloc(len);
1042   silc_buffer_pull_tail(client_id_list, len);
1043   silc_buffer_put(client_id_list, tmp, len);
1044
1045   /* Get client mode list */
1046   tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1047   if (!tmp)
1048     goto out;
1049
1050   client_mode_list = silc_buffer_alloc(len);
1051   silc_buffer_pull_tail(client_mode_list, len);
1052   silc_buffer_put(client_mode_list, tmp, len);
1053
1054   /* Get founder key */
1055   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1056   if (tmp)
1057     silc_public_key_payload_decode(tmp, len, &founder_key);
1058
1059   /* See whether we already have the channel. */
1060   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1061                                           SILC_STRING_UTF8, 256, NULL);
1062   if (!channel_namec)
1063     goto out;
1064   entry = silc_idlist_find_channel_by_name(server->local_list,
1065                                            channel_namec, &cache);
1066   if (!entry) {
1067     /* Add new channel */
1068
1069     SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1070                     (created == 0 ? "existing" : "created"), channel_name,
1071                     silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1072
1073     /* If the channel is found from global list we must move it to the
1074        local list. */
1075     entry = silc_idlist_find_channel_by_name(server->global_list,
1076                                              channel_namec, &cache);
1077     if (entry)
1078       silc_idlist_del_channel(server->global_list, entry);
1079
1080     /* Add the channel to our local list. */
1081     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1082                                     SILC_CHANNEL_MODE_NONE,
1083                                     silc_id_dup(SILC_ID_GET_ID(id),
1084                                                 SILC_ID_CHANNEL),
1085                                     server->router, NULL, NULL, hmac);
1086     if (!entry)
1087       goto out;
1088
1089     hmac = NULL;
1090     server->stat.my_channels++;
1091     server->stat.channels++;
1092   } else {
1093     /* The entry exists. */
1094
1095     /* If ID has changed, then update it to the cache too. */
1096     if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1097       silc_idlist_replace_channel_id(server->local_list, entry->id,
1098                                      SILC_ID_GET_ID(id));
1099
1100     entry->disabled = FALSE;
1101
1102     /* Remove the founder auth data if the mode is not set but we have
1103        them in the entry */
1104     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1105       silc_pkcs_public_key_free(entry->founder_key);
1106       entry->founder_key = NULL;
1107     }
1108   }
1109
1110   if (founder_key) {
1111     if (entry->founder_key)
1112       silc_pkcs_public_key_free(entry->founder_key);
1113     entry->founder_key = founder_key;
1114     founder_key = NULL;
1115   }
1116
1117   if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1118     silc_free(entry->hmac_name);
1119     entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1120   }
1121
1122   /* Get the ban list */
1123   tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1124   if (tmp && len > 2) {
1125     SilcArgumentPayload iargs;
1126     SilcUInt16 iargc;
1127     SILC_GET16_MSB(iargc, tmp);
1128     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1129     if (iargs) {
1130       /* Delete old ban list */
1131       if (entry->ban_list)
1132         silc_hash_table_free(entry->ban_list);
1133       entry->ban_list =
1134         silc_hash_table_alloc(0, silc_hash_ptr,
1135                               NULL, NULL, NULL,
1136                               silc_server_inviteban_destruct, entry, TRUE);
1137
1138       /* Add new ban list */
1139       silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1140       silc_argument_payload_free(iargs);
1141     }
1142   }
1143
1144   /* Get the invite list */
1145   tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1146   if (tmp && len > 2) {
1147     SilcArgumentPayload iargs;
1148     SilcUInt16 iargc;
1149     SILC_GET16_MSB(iargc, tmp);
1150     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1151     if (iargs) {
1152       /* Delete old invite list */
1153       if (entry->invite_list)
1154         silc_hash_table_free(entry->invite_list);
1155       entry->invite_list =
1156         silc_hash_table_alloc(0, silc_hash_ptr,
1157                               NULL, NULL, NULL,
1158                               silc_server_inviteban_destruct, entry, TRUE);
1159
1160       /* Add new invite list */
1161       silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1162       silc_argument_payload_free(iargs);
1163     }
1164   }
1165
1166   /* Get the topic */
1167   tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1168   if (tmp) {
1169     silc_free(entry->topic);
1170     entry->topic = strdup(tmp);
1171   }
1172
1173   /* Get channel public key list */
1174   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1175   if (tmp && server->server_type != SILC_ROUTER)
1176     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1177
1178   /* The the user limit */
1179   tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1180   if (tmp && len == 4)
1181     SILC_GET32_MSB(entry->user_limit, tmp);
1182
1183   /* If channel was not created we know there is global users on the
1184      channel. */
1185   entry->global_users = (created == 0 ? TRUE : FALSE);
1186
1187   /* If channel was just created the mask must be zero */
1188   if (!entry->global_users && mode)
1189     mode = 0;
1190
1191   /* Save channel mode */
1192   entry->mode = mode;
1193
1194   /* Save channel key */
1195   if (keyp) {
1196     if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1197       silc_server_save_channel_key(server, keyp, entry);
1198     silc_buffer_free(keyp);
1199   }
1200
1201   /* Save the users to the channel */
1202   silc_server_save_users_on_channel(server, cmd->sock, entry,
1203                                     SILC_ID_GET_ID(id2), client_id_list,
1204                                     client_mode_list, list_count);
1205   entry->users_resolved = TRUE;
1206
1207  out:
1208   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1209  err:
1210   silc_free(channel_namec);
1211   if (hmac)
1212     silc_hmac_free(hmac);
1213   silc_server_command_reply_free(cmd);
1214
1215   if (founder_key)
1216     silc_pkcs_public_key_free(founder_key);
1217   if (client_id_list)
1218     silc_buffer_free(client_id_list);
1219   if (client_mode_list)
1220     silc_buffer_free(client_mode_list);
1221 }
1222
1223 /* Received reply to STATS command.  */
1224
1225 SILC_SERVER_CMD_REPLY_FUNC(stats)
1226 {
1227   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1228   SilcServer server = cmd->server;
1229   SilcStatus status, error;
1230   unsigned char *tmp;
1231   SilcUInt32 tmp_len;
1232   SilcBufferStruct buf;
1233
1234   COMMAND_CHECK_STATUS;
1235
1236   /* Get statistics structure */
1237   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1238   if (server->server_type != SILC_ROUTER && tmp) {
1239     silc_buffer_set(&buf, tmp, tmp_len);
1240     silc_buffer_unformat(&buf,
1241                          SILC_STR_UI_INT(NULL),
1242                          SILC_STR_UI_INT(NULL),
1243                          SILC_STR_UI_INT(NULL),
1244                          SILC_STR_UI_INT(NULL),
1245                          SILC_STR_UI_INT(NULL),
1246                          SILC_STR_UI_INT(NULL),
1247                          SILC_STR_UI_INT(&server->stat.cell_clients),
1248                          SILC_STR_UI_INT(&server->stat.cell_channels),
1249                          SILC_STR_UI_INT(&server->stat.cell_servers),
1250                          SILC_STR_UI_INT(&server->stat.clients),
1251                          SILC_STR_UI_INT(&server->stat.channels),
1252                          SILC_STR_UI_INT(&server->stat.servers),
1253                          SILC_STR_UI_INT(&server->stat.routers),
1254                          SILC_STR_UI_INT(&server->stat.server_ops),
1255                          SILC_STR_UI_INT(&server->stat.router_ops),
1256                          SILC_STR_END);
1257   }
1258
1259   SILC_LOG_DEBUG(("stat.clients = %d", server->stat.clients));
1260
1261  out:
1262   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1263  err:
1264   silc_server_command_reply_free(cmd);
1265 }
1266
1267 SILC_SERVER_CMD_REPLY_FUNC(users)
1268 {
1269   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1270   SilcServer server = cmd->server;
1271   SilcStatus status, error;
1272   SilcChannelEntry channel;
1273   SilcID id;
1274   SilcBuffer client_id_list;
1275   SilcBuffer client_mode_list;
1276   unsigned char *tmp;
1277   SilcUInt32 tmp_len;
1278   SilcUInt32 list_count;
1279
1280   COMMAND_CHECK_STATUS;
1281
1282   /* Get channel ID */
1283   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1284     goto out;
1285
1286   /* Get channel entry */
1287   channel = silc_idlist_find_channel_by_id(server->local_list,
1288                                            SILC_ID_GET_ID(id), NULL);
1289   if (!channel) {
1290     channel = silc_idlist_find_channel_by_id(server->global_list,
1291                                              SILC_ID_GET_ID(id), NULL);
1292     if (!channel) {
1293       SilcBuffer idp;
1294
1295       if (cmd->pending || server->server_type != SILC_SERVER)
1296         goto out;
1297
1298       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1299       silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1300                                SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1301                                1, 5, idp->data, silc_buffer_len(idp));
1302       silc_buffer_free(idp);
1303
1304       /* Register pending command callback. After we've received the channel
1305          information we will reprocess this command reply by re-calling this
1306          USERS command reply callback. */
1307       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1308                                   server->cmd_ident,
1309                                   silc_server_command_reply_users, cmd);
1310
1311       cmd->pending = TRUE;
1312       return;
1313     }
1314   }
1315
1316   /* Get the list count */
1317   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1318   if (!tmp)
1319     goto out;
1320   SILC_GET32_MSB(list_count, tmp);
1321
1322   /* Get Client ID list */
1323   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1324   if (!tmp)
1325     goto out;
1326
1327   client_id_list = silc_buffer_alloc(tmp_len);
1328   silc_buffer_pull_tail(client_id_list, tmp_len);
1329   silc_buffer_put(client_id_list, tmp, tmp_len);
1330
1331   /* Get client mode list */
1332   tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1333   if (!tmp)
1334     goto out;
1335
1336   client_mode_list = silc_buffer_alloc(tmp_len);
1337   silc_buffer_pull_tail(client_mode_list, tmp_len);
1338   silc_buffer_put(client_mode_list, tmp, tmp_len);
1339
1340   /* Save the users to the channel */
1341   silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1342                                     client_id_list, client_mode_list,
1343                                     list_count);
1344
1345   channel->global_users = silc_server_channel_has_global(channel);
1346   channel->users_resolved = TRUE;
1347
1348   silc_buffer_free(client_id_list);
1349   silc_buffer_free(client_mode_list);
1350
1351  out:
1352   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1353  err:
1354   silc_server_command_reply_free(cmd);
1355 }
1356
1357 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1358 {
1359   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1360   SilcServer server = cmd->server;
1361   SilcStatus status, error;
1362   SilcClientEntry client = NULL;
1363   SilcServerEntry server_entry = NULL;
1364   SilcClientID client_id;
1365   SilcServerID server_id;
1366   unsigned char *tmp;
1367   SilcUInt32 len;
1368   SilcIDPayload idp = NULL;
1369   SilcIdType id_type;
1370   SilcPublicKey public_key = NULL;
1371
1372   COMMAND_CHECK_STATUS;
1373
1374   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1375   if (!tmp)
1376     goto out;
1377   idp = silc_id_payload_parse(tmp, len);
1378   if (!idp)
1379     goto out;
1380
1381   /* Get the public key payload */
1382   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1383   if (!tmp)
1384     goto out;
1385
1386   /* Decode the public key payload */
1387   if (!silc_public_key_payload_decode(tmp, len, &public_key))
1388     goto out;
1389
1390   id_type = silc_id_payload_get_type(idp);
1391   if (id_type == SILC_ID_CLIENT) {
1392     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1393
1394     client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1395                                            TRUE, NULL);
1396     if (!client) {
1397       client = silc_idlist_find_client_by_id(server->global_list,
1398                                              &client_id, TRUE, NULL);
1399       if (!client)
1400         goto out;
1401     }
1402
1403     if (!client->data.public_key) {
1404       /* Add client's public key to repository */
1405       if (!silc_server_get_public_key_by_client(server, client, NULL))
1406         silc_skr_add_public_key_simple(server->repository,
1407                                        public_key,
1408                                        SILC_SKR_USAGE_IDENTIFICATION,
1409                                        client, NULL);
1410       client->data.public_key = public_key;
1411       public_key = NULL;
1412     }
1413   } else if (id_type == SILC_ID_SERVER) {
1414     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1415
1416     server_entry = silc_idlist_find_server_by_id(server->local_list,
1417                                                  &server_id, TRUE, NULL);
1418     if (!server_entry) {
1419       server_entry = silc_idlist_find_server_by_id(server->global_list,
1420                                                    &server_id, TRUE, NULL);
1421       if (!server_entry)
1422         goto out;
1423     }
1424
1425     server_entry->data.public_key = public_key;
1426     public_key = NULL;
1427   } else {
1428     goto out;
1429   }
1430
1431  out:
1432   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1433   if (idp)
1434     silc_id_payload_free(idp);
1435   if (public_key)
1436     silc_pkcs_public_key_free(public_key);
1437  err:
1438   silc_server_command_reply_free(cmd);
1439 }
1440
1441 SILC_SERVER_CMD_REPLY_FUNC(list)
1442 {
1443   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1444   SilcServer server = cmd->server;
1445   SilcStatus status, error;
1446   SilcID id;
1447   SilcChannelEntry channel;
1448   SilcIDCacheEntry cache;
1449   unsigned char *tmp, *name, *namec = NULL, *topic;
1450   SilcUInt32 usercount = 0;
1451
1452   COMMAND_CHECK_STATUS;
1453
1454   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1455     goto out;
1456
1457   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1458   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1459   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1460   if (tmp)
1461     SILC_GET32_MSB(usercount, tmp);
1462
1463   namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1464                                   256, NULL);
1465   if (!namec)
1466     goto out;
1467
1468   /* Add the channel entry if we do not have it already */
1469   channel = silc_idlist_find_channel_by_name(server->local_list,
1470                                              namec, &cache);
1471   if (!channel)
1472     channel = silc_idlist_find_channel_by_name(server->global_list,
1473                                                namec, &cache);
1474   if (!channel) {
1475     /* If router did not find such channel in its lists then this must
1476        be bogus channel or some router in the net is buggy. */
1477     if (server->server_type != SILC_SERVER)
1478       goto out;
1479
1480     channel = silc_idlist_add_channel(server->global_list, strdup(name),
1481                                       SILC_CHANNEL_MODE_NONE,
1482                                       silc_id_dup(SILC_ID_GET_ID(id),
1483                                                   SILC_ID_CHANNEL),
1484                                       server->router, NULL, NULL, NULL);
1485     if (!channel)
1486       goto out;
1487   }
1488
1489   channel->user_count = usercount;
1490
1491   if (topic) {
1492     silc_free(channel->topic);
1493     channel->topic = strdup(topic);
1494   }
1495
1496   /* Pending callbacks are not executed if this was an list entry */
1497   if (status != SILC_STATUS_OK &&
1498       status != SILC_STATUS_LIST_END) {
1499     silc_server_command_reply_free(cmd);
1500     return;
1501   }
1502
1503  out:
1504   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1505  err:
1506   silc_free(namec);
1507   silc_server_command_reply_free(cmd);
1508 }
1509
1510 SILC_SERVER_CMD_REPLY_FUNC(watch)
1511 {
1512   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1513   SilcStatus status, error;
1514
1515   COMMAND_CHECK_STATUS;
1516
1517  out:
1518   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1519  err:
1520   silc_server_command_reply_free(cmd);
1521 }
1522
1523 SILC_SERVER_CMD_REPLY_FUNC(ping)
1524 {
1525   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1526   SilcStatus status, error;
1527
1528   COMMAND_CHECK_STATUS;
1529
1530  out:
1531   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1532  err:
1533   silc_server_command_reply_free(cmd);
1534 }