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