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