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