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       /* Statistics */
966       cmd->server->stat.commands_sent++;
967
968       /* entry isn't known so we IDENTIFY it. otherwise the
969          silc_server_command_motd won't know about it and tell
970          the client that there is no such server */
971       buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
972                                               ++server->cmd_ident, 5,
973                                               1, NULL, 0, 2, NULL, 0,
974                                               3, NULL, 0, 4, NULL, 0,
975                                               5, tmp, tmp_len);
976       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
977                               SILC_PACKET_COMMAND, 0, buffer->data,
978                               buffer->len, TRUE);
979       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
980                                   server->cmd_ident,
981                                   silc_server_command_reply_motd,
982                                   cmd);
983       silc_buffer_free(buffer);
984       return;
985     }
986   }
987
988   /* Get the motd */
989   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
990   if (tmp_len > 256)
991     tmp = NULL;
992
993   entry->motd = tmp;
994
995  out:
996   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
997  err:
998   silc_server_command_reply_free(cmd);
999
1000   if (entry)
1001     entry->motd = NULL;
1002 }
1003
1004 /* Received reply for forwarded JOIN command. Router has created or joined
1005    the client to the channel. We save some channel information locally
1006    for future use. */
1007
1008 SILC_SERVER_CMD_REPLY_FUNC(join)
1009 {
1010   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1011   SilcServer server = cmd->server;
1012   SilcIDCacheEntry cache = NULL;
1013   SilcStatus status, error;
1014   SilcChannelID *id;
1015   SilcClientID *client_id = NULL;
1016   SilcChannelEntry entry;
1017   SilcHmac hmac = NULL;
1018   SilcUInt32 id_len, len, list_count;
1019   unsigned char *id_string;
1020   char *channel_name, *channel_namec = NULL, *tmp;
1021   SilcUInt32 mode, created;
1022   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
1023   SilcPublicKey founder_key = NULL;
1024
1025   COMMAND_CHECK_STATUS;
1026
1027   /* Get channel name */
1028   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
1029   if (!channel_name)
1030     goto out;
1031
1032   /* Get channel ID */
1033   id_string = silc_argument_get_arg_type(cmd->args, 3, &id_len);
1034   if (!id_string)
1035     goto out;
1036
1037   /* Get client ID */
1038   tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
1039   if (!tmp)
1040     goto out;
1041   client_id = silc_id_payload_parse_id(tmp, len, NULL);
1042   if (!client_id)
1043     goto out;
1044
1045   /* Get mode mask */
1046   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1047   if (!tmp)
1048     goto out;
1049   SILC_GET32_MSB(mode, tmp);
1050
1051   /* Get created boolean value */
1052   tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1053   if (!tmp)
1054     goto out;
1055   SILC_GET32_MSB(created, tmp);
1056   if (created != 0 && created != 1)
1057     goto out;
1058
1059   /* Get channel key */
1060   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1061   if (tmp) {
1062     keyp = silc_buffer_alloc(len);
1063     silc_buffer_pull_tail(keyp, SILC_BUFFER_END(keyp));
1064     silc_buffer_put(keyp, tmp, len);
1065   }
1066
1067   /* Parse the Channel ID */
1068   id = silc_id_payload_parse_id(id_string, id_len, NULL);
1069   if (!id)
1070     goto out;
1071
1072   /* Get hmac */
1073   tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1074   if (tmp) {
1075     if (!silc_hmac_alloc(tmp, NULL, &hmac))
1076       goto out;
1077   }
1078
1079   /* Get the list count */
1080   tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1081   if (!tmp)
1082     goto out;
1083   SILC_GET32_MSB(list_count, tmp);
1084
1085   /* Get Client ID list */
1086   tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1087   if (!tmp)
1088     goto out;
1089
1090   client_id_list = silc_buffer_alloc(len);
1091   silc_buffer_pull_tail(client_id_list, len);
1092   silc_buffer_put(client_id_list, tmp, len);
1093
1094   /* Get client mode list */
1095   tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1096   if (!tmp)
1097     goto out;
1098
1099   client_mode_list = silc_buffer_alloc(len);
1100   silc_buffer_pull_tail(client_mode_list, len);
1101   silc_buffer_put(client_mode_list, tmp, len);
1102
1103   /* Get founder key */
1104   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1105   if (tmp)
1106     silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
1107
1108   /* See whether we already have the channel. */
1109   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1110                                           SILC_STRING_UTF8, 256, NULL);
1111   if (!channel_namec)
1112     goto out;
1113   entry = silc_idlist_find_channel_by_name(server->local_list,
1114                                            channel_namec, &cache);
1115   if (!entry) {
1116     /* Add new channel */
1117
1118     SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1119                     (created == 0 ? "existing" : "created"), channel_name,
1120                     silc_id_render(id, SILC_ID_CHANNEL)));
1121
1122     /* If the channel is found from global list we must move it to the
1123        local list. */
1124     entry = silc_idlist_find_channel_by_name(server->global_list,
1125                                              channel_namec, &cache);
1126     if (entry)
1127       silc_idlist_del_channel(server->global_list, entry);
1128
1129     /* Add the channel to our local list. */
1130     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1131                                     SILC_CHANNEL_MODE_NONE, id,
1132                                     server->router, NULL, hmac, 0);
1133     if (!entry) {
1134       silc_free(id);
1135       goto out;
1136     }
1137     hmac = NULL;
1138     server->stat.my_channels++;
1139     server->stat.channels++;
1140   } else {
1141     /* The entry exists. */
1142
1143     /* If ID has changed, then update it to the cache too. */
1144     if (!SILC_ID_CHANNEL_COMPARE(entry->id, id))
1145       silc_idlist_replace_channel_id(server->local_list, entry->id, id);
1146
1147     entry->disabled = FALSE;
1148
1149     /* Remove the founder auth data if the mode is not set but we have
1150        them in the entry */
1151     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1152       silc_pkcs_public_key_free(entry->founder_key);
1153       entry->founder_key = NULL;
1154     }
1155   }
1156
1157   if (founder_key) {
1158     if (entry->founder_key)
1159       silc_pkcs_public_key_free(entry->founder_key);
1160     entry->founder_key = founder_key;
1161     founder_key = NULL;
1162   }
1163
1164   if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1165     silc_free(entry->hmac_name);
1166     entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1167   }
1168
1169   /* Get the ban list */
1170   tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1171   if (tmp && len > 2) {
1172     SilcArgumentPayload iargs;
1173     SilcUInt16 iargc;
1174     SILC_GET16_MSB(iargc, tmp);
1175     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1176     if (iargs) {
1177       /* Delete old ban list */
1178       if (entry->ban_list)
1179         silc_hash_table_free(entry->ban_list);
1180       entry->ban_list =
1181         silc_hash_table_alloc(0, silc_hash_ptr,
1182                               NULL, NULL, NULL,
1183                               silc_server_inviteban_destruct, entry, TRUE);
1184
1185       /* Add new ban list */
1186       silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1187       silc_argument_payload_free(iargs);
1188     }
1189   }
1190
1191   /* Get the invite list */
1192   tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1193   if (tmp && len > 2) {
1194     SilcArgumentPayload iargs;
1195     SilcUInt16 iargc;
1196     SILC_GET16_MSB(iargc, tmp);
1197     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1198     if (iargs) {
1199       /* Delete old invite list */
1200       if (entry->invite_list)
1201         silc_hash_table_free(entry->invite_list);
1202       entry->invite_list =
1203         silc_hash_table_alloc(0, silc_hash_ptr,
1204                               NULL, NULL, NULL,
1205                               silc_server_inviteban_destruct, entry, TRUE);
1206
1207       /* Add new invite list */
1208       silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1209       silc_argument_payload_free(iargs);
1210     }
1211   }
1212
1213   /* Get the topic */
1214   tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1215   if (tmp) {
1216     silc_free(entry->topic);
1217     entry->topic = strdup(tmp);
1218   }
1219
1220   /* Get channel public key list */
1221   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1222   if (tmp && server->server_type != SILC_ROUTER)
1223     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1224
1225   /* The the user limit */
1226   tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1227   if (tmp && len == 4)
1228     SILC_GET32_MSB(entry->user_limit, tmp);
1229
1230   /* If channel was not created we know there is global users on the
1231      channel. */
1232   entry->global_users = (created == 0 ? TRUE : FALSE);
1233
1234   /* If channel was just created the mask must be zero */
1235   if (!entry->global_users && mode) {
1236     SILC_LOG_DEBUG(("Buggy router `%s' sent non-zero mode mask for "
1237                     "new channel, forcing it to zero", cmd->sock->hostname));
1238     mode = 0;
1239   }
1240
1241   /* Save channel mode */
1242   entry->mode = mode;
1243
1244   /* Save channel key */
1245   if (keyp) {
1246     if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1247       silc_server_save_channel_key(server, keyp, entry);
1248     silc_buffer_free(keyp);
1249   }
1250
1251   /* Save the users to the channel */
1252   silc_server_save_users_on_channel(server, cmd->sock, entry,
1253                                     client_id, client_id_list,
1254                                     client_mode_list, list_count);
1255   entry->users_resolved = TRUE;
1256
1257  out:
1258   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1259  err:
1260   silc_free(channel_namec);
1261   if (hmac)
1262     silc_hmac_free(hmac);
1263   silc_free(client_id);
1264   silc_server_command_reply_free(cmd);
1265
1266   silc_pkcs_public_key_free(founder_key);
1267   if (client_id_list)
1268     silc_buffer_free(client_id_list);
1269   if (client_mode_list)
1270     silc_buffer_free(client_mode_list);
1271 }
1272
1273 /* Received reply to STATS command.  */
1274
1275 SILC_SERVER_CMD_REPLY_FUNC(stats)
1276 {
1277   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1278   SilcServer server = cmd->server;
1279   SilcStatus status, error;
1280   unsigned char *tmp;
1281   SilcUInt32 tmp_len;
1282   SilcBufferStruct buf;
1283
1284   COMMAND_CHECK_STATUS;
1285
1286   /* Get statistics structure */
1287   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1288   if (server->server_type != SILC_ROUTER && tmp) {
1289     silc_buffer_set(&buf, tmp, tmp_len);
1290     silc_buffer_unformat(&buf,
1291                          SILC_STR_UI_INT(NULL),
1292                          SILC_STR_UI_INT(NULL),
1293                          SILC_STR_UI_INT(NULL),
1294                          SILC_STR_UI_INT(NULL),
1295                          SILC_STR_UI_INT(NULL),
1296                          SILC_STR_UI_INT(NULL),
1297                          SILC_STR_UI_INT(&server->stat.cell_clients),
1298                          SILC_STR_UI_INT(&server->stat.cell_channels),
1299                          SILC_STR_UI_INT(&server->stat.cell_servers),
1300                          SILC_STR_UI_INT(&server->stat.clients),
1301                          SILC_STR_UI_INT(&server->stat.channels),
1302                          SILC_STR_UI_INT(&server->stat.servers),
1303                          SILC_STR_UI_INT(&server->stat.routers),
1304                          SILC_STR_UI_INT(&server->stat.server_ops),
1305                          SILC_STR_UI_INT(&server->stat.router_ops),
1306                          SILC_STR_END);
1307   }
1308
1309  out:
1310   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1311  err:
1312   silc_server_command_reply_free(cmd);
1313 }
1314
1315 SILC_SERVER_CMD_REPLY_FUNC(users)
1316 {
1317   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1318   SilcServer server = cmd->server;
1319   SilcStatus status, error;
1320   SilcChannelEntry channel;
1321   SilcChannelID *channel_id = NULL;
1322   SilcBuffer client_id_list;
1323   SilcBuffer client_mode_list;
1324   unsigned char *tmp;
1325   SilcUInt32 tmp_len;
1326   SilcUInt32 list_count;
1327
1328   COMMAND_CHECK_STATUS;
1329
1330   /* Get channel ID */
1331   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1332   if (!tmp)
1333     goto out;
1334   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1335   if (!channel_id)
1336     goto out;
1337
1338   /* Get channel entry */
1339   channel = silc_idlist_find_channel_by_id(server->local_list,
1340                                            channel_id, NULL);
1341   if (!channel) {
1342     channel = silc_idlist_find_channel_by_id(server->global_list,
1343                                              channel_id, NULL);
1344     if (!channel) {
1345       SilcBuffer idp;
1346
1347       if (server->server_type != SILC_SERVER)
1348         goto out;
1349
1350       idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1351       silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1352                                SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1353                                1, 5, idp->data, idp->len);
1354       silc_buffer_free(idp);
1355
1356       /* Register pending command callback. After we've received the channel
1357          information we will reprocess this command reply by re-calling this
1358          USERS command reply callback. */
1359       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1360                                   server->cmd_ident,
1361                                   silc_server_command_reply_users, cmd);
1362       return;
1363     }
1364   }
1365
1366   /* Get the list count */
1367   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1368   if (!tmp)
1369     goto out;
1370   SILC_GET32_MSB(list_count, tmp);
1371
1372   /* Get Client ID list */
1373   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1374   if (!tmp)
1375     goto out;
1376
1377   client_id_list = silc_buffer_alloc(tmp_len);
1378   silc_buffer_pull_tail(client_id_list, tmp_len);
1379   silc_buffer_put(client_id_list, tmp, tmp_len);
1380
1381   /* Get client mode list */
1382   tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1383   if (!tmp)
1384     goto out;
1385
1386   client_mode_list = silc_buffer_alloc(tmp_len);
1387   silc_buffer_pull_tail(client_mode_list, tmp_len);
1388   silc_buffer_put(client_mode_list, tmp, tmp_len);
1389
1390   /* Save the users to the channel */
1391   silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1392                                     client_id_list, client_mode_list,
1393                                     list_count);
1394
1395   channel->global_users = silc_server_channel_has_global(channel);
1396   channel->users_resolved = TRUE;
1397
1398   silc_buffer_free(client_id_list);
1399   silc_buffer_free(client_mode_list);
1400
1401  out:
1402   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1403   silc_free(channel_id);
1404  err:
1405   silc_server_command_reply_free(cmd);
1406 }
1407
1408 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1409 {
1410   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1411   SilcServer server = cmd->server;
1412   SilcStatus status, error;
1413   SilcClientEntry client = NULL;
1414   SilcServerEntry server_entry = NULL;
1415   SilcClientID *client_id = NULL;
1416   SilcServerID *server_id = NULL;
1417   unsigned char *tmp;
1418   SilcUInt32 len;
1419   SilcIDPayload idp = NULL;
1420   SilcIdType id_type;
1421   SilcPublicKey public_key = NULL;
1422
1423   COMMAND_CHECK_STATUS;
1424
1425   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1426   if (!tmp)
1427     goto out;
1428   idp = silc_id_payload_parse(tmp, len);
1429   if (!idp)
1430     goto out;
1431
1432   /* Get the public key payload */
1433   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1434   if (!tmp)
1435     goto out;
1436
1437   /* Decode the public key payload */
1438   if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
1439     goto out;
1440
1441   id_type = silc_id_payload_get_type(idp);
1442   if (id_type == SILC_ID_CLIENT) {
1443     client_id = silc_id_payload_get_id(idp);
1444
1445     client = silc_idlist_find_client_by_id(server->local_list, client_id,
1446                                            TRUE, NULL);
1447     if (!client) {
1448       client = silc_idlist_find_client_by_id(server->global_list,
1449                                              client_id, TRUE, NULL);
1450       if (!client)
1451         goto out;
1452     }
1453
1454     if (!client->data.public_key) {
1455       if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
1456                                            client, NULL))
1457         silc_hash_table_add(server->pk_hash, public_key, client);
1458
1459       client->data.public_key = public_key;
1460       public_key = NULL;
1461     }
1462   } else if (id_type == SILC_ID_SERVER) {
1463     server_id = silc_id_payload_get_id(idp);
1464
1465     server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
1466                                                  TRUE, NULL);
1467     if (!server_entry) {
1468       server_entry = silc_idlist_find_server_by_id(server->global_list,
1469                                                    server_id, TRUE, NULL);
1470       if (!server_entry)
1471         goto out;
1472     }
1473
1474     server_entry->data.public_key = public_key;
1475     public_key = NULL;
1476   } else {
1477     goto out;
1478   }
1479
1480  out:
1481   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1482   if (idp)
1483     silc_id_payload_free(idp);
1484   silc_free(client_id);
1485   silc_free(server_id);
1486   if (public_key)
1487     silc_pkcs_public_key_free(public_key);
1488  err:
1489   silc_server_command_reply_free(cmd);
1490 }
1491
1492 SILC_SERVER_CMD_REPLY_FUNC(list)
1493 {
1494   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1495   SilcServer server = cmd->server;
1496   SilcStatus status, error;
1497   SilcChannelID *channel_id = NULL;
1498   SilcChannelEntry channel;
1499   SilcIDCacheEntry cache;
1500   SilcUInt32 len;
1501   unsigned char *tmp, *name, *namec = NULL, *topic;
1502   SilcUInt32 usercount = 0;
1503   bool global_list = FALSE;
1504
1505   COMMAND_CHECK_STATUS;
1506
1507   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1508   if (!tmp)
1509     goto out;
1510   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1511   if (!channel_id)
1512     goto out;
1513
1514   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1515   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1516   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1517   if (tmp)
1518     SILC_GET32_MSB(usercount, tmp);
1519
1520   namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1521                                   256, NULL);
1522   if (!namec)
1523     goto out;
1524
1525   /* Add the channel entry if we do not have it already */
1526   channel = silc_idlist_find_channel_by_name(server->local_list,
1527                                              namec, &cache);
1528   if (!channel) {
1529     channel = silc_idlist_find_channel_by_name(server->global_list,
1530                                                namec, &cache);
1531     global_list = TRUE;
1532   }
1533   if (!channel) {
1534     /* If router did not find such channel in its lists then this must
1535        be bogus channel or some router in the net is buggy. */
1536     if (server->server_type != SILC_SERVER)
1537       goto out;
1538
1539     channel = silc_idlist_add_channel(server->global_list, strdup(name),
1540                                       SILC_CHANNEL_MODE_NONE, channel_id,
1541                                       server->router, NULL, NULL,
1542                                       time(NULL) + 60);
1543     if (!channel)
1544       goto out;
1545     channel_id = NULL;
1546   } else {
1547     /* Found, update expiry */
1548     if (global_list && server->server_type == SILC_SERVER)
1549       cache->expire = time(NULL) + 60;
1550   }
1551
1552   channel->user_count = usercount;
1553
1554   if (topic) {
1555     silc_free(channel->topic);
1556     channel->topic = strdup(topic);
1557   }
1558
1559   /* Pending callbacks are not executed if this was an list entry */
1560   if (status != SILC_STATUS_OK &&
1561       status != SILC_STATUS_LIST_END) {
1562     silc_server_command_reply_free(cmd);
1563     return;
1564   }
1565
1566   /* Now purge all old entries from the global list, otherwise we'll might
1567      have non-existent entries for long periods of time in the cache. */
1568   silc_idcache_purge(server->global_list->channels);
1569
1570  out:
1571   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1572   silc_free(channel_id);
1573  err:
1574   silc_free(namec);
1575   silc_server_command_reply_free(cmd);
1576 }
1577
1578 SILC_SERVER_CMD_REPLY_FUNC(watch)
1579 {
1580   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1581   SilcStatus status, error;
1582
1583   COMMAND_CHECK_STATUS;
1584
1585  out:
1586   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1587  err:
1588   silc_server_command_reply_free(cmd);
1589 }
1590
1591 SILC_SERVER_CMD_REPLY_FUNC(ping)
1592 {
1593   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1594   SilcStatus status, error;
1595
1596   COMMAND_CHECK_STATUS;
1597
1598  out:
1599   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1600  err:
1601   silc_server_command_reply_free(cmd);
1602 }