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