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