acf1e2dd4438f94729db70a1bfa75c4d3bfcd88e
[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                       hostname ? hostname : "", nick));
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
537     /* Remove the old cache entry and create a new one */
538     silc_idcache_del_by_context(global ? server->global_list->clients :
539                                 server->local_list->clients, client, NULL);
540     silc_idcache_add(global ? server->global_list->clients :
541                      server->local_list->clients, nickname, client->id,
542                      client);
543   }
544
545   /* If client is global and is not on any channel then add that we'll
546      expire the entry after a while. */
547   if (global) {
548     silc_idlist_find_client_by_id(server->global_list, client->id,
549                                   FALSE, &cache);
550     if (!silc_hash_table_count(client->channels))
551       silc_dlist_add(server->expired_clients, client);
552   }
553
554   return TRUE;
555 }
556
557 /* Received reply for WHOWAS command. Cache the client information only for
558    a short period of time. */
559
560 SILC_SERVER_CMD_REPLY_FUNC(whowas)
561 {
562   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
563   SilcStatus status, error;
564
565   COMMAND_CHECK_STATUS;
566
567   if (!silc_server_command_reply_whowas_save(cmd))
568     goto out;
569
570   /* Pending callbacks are not executed if this was an list entry */
571   if (status != SILC_STATUS_OK &&
572       status != SILC_STATUS_LIST_END) {
573     silc_server_command_reply_free(cmd);
574     return;
575   }
576
577  out:
578   silc_server_command_process_error(cmd, error);
579   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
580   silc_server_command_reply_free(cmd);
581   return;
582
583  err:
584   silc_server_command_process_error(cmd, error);
585   silc_server_command_reply_free(cmd);
586 }
587
588 /* Caches the received IDENTIFY information. */
589
590 static char
591 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
592 {
593   SilcServer server = cmd->server;
594   SilcUInt32 len, id_len;
595   unsigned char *id_data;
596   char *name, *info;
597   SilcClientID client_id;
598   SilcServerID server_id;
599   SilcChannelID*channel_id;
600   SilcClientEntry client;
601   SilcServerEntry server_entry;
602   SilcChannelEntry channel;
603   char global = FALSE;
604   char nick[128 + 1];
605   SilcIDPayload idp = NULL;
606   SilcIdType id_type;
607
608   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
609   if (!id_data)
610     return FALSE;
611   idp = silc_id_payload_parse(id_data, id_len);
612   if (!idp)
613     return FALSE;
614
615   name = silc_argument_get_arg_type(cmd->args, 3, &len);
616   info = silc_argument_get_arg_type(cmd->args, 4, &len);
617
618   id_type = silc_id_payload_get_type(idp);
619
620   switch (id_type) {
621   case SILC_ID_CLIENT:
622     if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
623       goto error;
624
625     SILC_LOG_DEBUG(("Received client information"));
626
627     client = silc_idlist_find_client_by_id(server->local_list,
628                                            &client_id, FALSE, NULL);
629     if (!client) {
630       client = silc_idlist_find_client_by_id(server->global_list, &client_id,
631                                              FALSE, NULL);
632       global = TRUE;
633     }
634     if (!client) {
635       /* If router did not find such Client ID in its lists then this must
636          be bogus client or some router in the net is buggy. */
637       if (server->server_type != SILC_SERVER)
638         goto error;
639
640       /* Take nickname */
641       if (name)
642         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
643
644       /* We don't have that client anywhere, add it. The client is added
645          to global list since server didn't have it in the lists so it must be
646          global. */
647       client = silc_idlist_add_client(server->global_list,
648                                       nick[0] ? nick : NULL, info, NULL,
649                                       silc_id_dup(&client_id, SILC_ID_CLIENT),
650                                       silc_packet_get_context(cmd->sock),
651                                       NULL);
652       if (!client) {
653         SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
654         goto error;
655       }
656
657       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
658       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
659       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
660     } else {
661       /* We have the client already, update the data */
662
663       SILC_LOG_DEBUG(("Updating client data"));
664
665       /* Take nickname */
666       if (name) {
667         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
668
669         /* Check nickname */
670         name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
671                                      128, NULL);
672         if (!name) {
673           SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
674                           "reply ", nick));
675           return FALSE;
676         }
677
678         /* Remove the old cache entry */
679         silc_idcache_del_by_context(global ? server->global_list->clients :
680                                     server->local_list->clients, client, NULL);
681
682         silc_free(client->nickname);
683         client->nickname = strdup(nick);
684
685         /* Add new cache entry */
686         silc_idcache_add(global ? server->global_list->clients :
687                          server->local_list->clients, name, client->id,
688                          client);
689       }
690
691       if (info) {
692         silc_free(client->username);
693         client->username = strdup(info);
694       }
695
696       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
697       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
698     }
699
700     break;
701
702   case SILC_ID_SERVER:
703     if (!name)
704       goto error;
705
706     if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
707       goto error;
708
709     SILC_LOG_DEBUG(("Received server information"));
710
711     server_entry = silc_idlist_find_server_by_id(server->local_list,
712                                                  &server_id, FALSE, NULL);
713     if (!server_entry)
714       server_entry = silc_idlist_find_server_by_id(server->global_list,
715                                                    &server_id, FALSE, NULL);
716     if (!server_entry) {
717       /* If router did not find such Server ID in its lists then this must
718          be bogus server or some router in the net is buggy. */
719       if (server->server_type != SILC_SERVER)
720         goto error;
721
722       /* We don't have that server anywhere, add it. */
723       server_entry = silc_idlist_add_server(server->global_list,
724                                             strdup(name), 0,
725                                             silc_id_dup(&server_id,
726                                                         SILC_ID_SERVER),
727                                             server->router,
728                                             SILC_PRIMARY_ROUTE(server));
729       if (!server_entry)
730         goto error;
731
732       server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
733       server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
734       server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
735     }
736
737     break;
738
739   case SILC_ID_CHANNEL:
740     if (!name)
741       goto error;
742
743     if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
744       goto error;
745
746     SILC_LOG_DEBUG(("Received channel information"));
747
748     /* Check channel name */
749     info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
750                                    256, NULL);
751     if (!info)
752       goto error;
753
754     channel = silc_idlist_find_channel_by_name(server->local_list,
755                                                info, NULL);
756     if (!channel)
757       channel = silc_idlist_find_channel_by_name(server->global_list,
758                                                  info, NULL);
759     if (!channel) {
760       /* If router did not find such Channel ID in its lists then this must
761          be bogus channel or some router in the net is buggy. */
762       if (server->server_type != SILC_SERVER) {
763         silc_free(info);
764         goto error;
765       }
766
767       /* We don't have that channel anywhere, add it. */
768       channel = silc_idlist_add_channel(server->global_list, strdup(name),
769                                         SILC_CHANNEL_MODE_NONE,
770                                         silc_id_dup(&channel_id,
771                                                     SILC_ID_CHANNEL),
772                                         server->router, NULL, NULL, 0);
773       if (!channel) {
774         silc_free(info);
775         goto error;
776       }
777       silc_free(info);
778     }
779
780     break;
781   }
782
783   silc_id_payload_free(idp);
784   return TRUE;
785
786  error:
787   silc_id_payload_free(idp);
788   return FALSE;
789 }
790
791 /* Received reply for forwarded IDENTIFY command. We have received the
792    requested identify information now and we will cache it. After this we
793    will call the pending command so that the requestee gets the information
794    after all. */
795
796 SILC_SERVER_CMD_REPLY_FUNC(identify)
797 {
798   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
799   SilcStatus status, error;
800
801   COMMAND_CHECK_STATUS;
802
803   if (!silc_server_command_reply_identify_save(cmd))
804     goto out;
805
806   /* Pending callbacks are not executed if this was an list entry */
807   if (status != SILC_STATUS_OK &&
808       status != SILC_STATUS_LIST_END) {
809     silc_server_command_reply_free(cmd);
810     return;
811   }
812
813  out:
814   silc_server_command_process_error(cmd, error);
815   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
816   silc_server_command_reply_free(cmd);
817   return;
818
819  err:
820   silc_server_command_process_error(cmd, error);
821   silc_server_command_reply_free(cmd);
822 }
823
824 /* Received reply fro INFO command. Cache the server and its information */
825
826 SILC_SERVER_CMD_REPLY_FUNC(info)
827 {
828   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
829   SilcServer server = cmd->server;
830   SilcStatus status, error;
831   SilcServerEntry entry;
832   SilcID id;
833   SilcUInt32 tmp_len;
834   unsigned char *tmp, *name;
835
836   COMMAND_CHECK_STATUS;
837
838   /* Get Server ID */
839   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
840     goto out;
841
842   /* Get the name */
843   name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
844   if (!name)
845     goto out;
846
847   entry = silc_idlist_find_server_by_id(server->local_list,
848                                         SILC_ID_GET_ID(id),
849                                         FALSE, NULL);
850   if (!entry) {
851     entry = silc_idlist_find_server_by_id(server->global_list,
852                                           SILC_ID_GET_ID(id),
853                                           FALSE, NULL);
854     if (!entry) {
855       /* Add the server to global list */
856       entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
857                                      silc_id_dup(SILC_ID_GET_ID(id),
858                                                  SILC_ID_SERVER),
859                                      silc_packet_get_context(cmd->sock),
860                                      cmd->sock);
861       if (!entry)
862         goto out;
863
864       entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
865     }
866   }
867
868   /* Get the info string */
869   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
870   if (tmp_len > 256)
871     tmp = NULL;
872
873   entry->server_info = tmp ? strdup(tmp) : NULL;
874
875  out:
876   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
877  err:
878   silc_server_command_reply_free(cmd);
879 }
880
881 /* Received reply fro MOTD command. */
882
883 SILC_SERVER_CMD_REPLY_FUNC(motd)
884 {
885   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
886   SilcServer server = cmd->server;
887   SilcStatus status, error;
888   SilcServerEntry entry = NULL;
889   SilcID id;
890   SilcUInt32 tmp_len;
891   unsigned char *tmp;
892
893   COMMAND_CHECK_STATUS;
894
895   /* Get Server ID */
896   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
897     goto out;
898
899   entry = silc_idlist_find_server_by_id(server->local_list,
900                                         SILC_ID_GET_ID(id),
901                                         TRUE, NULL);
902   if (!entry) {
903     entry = silc_idlist_find_server_by_id(server->global_list,
904                                           SILC_ID_GET_ID(id),
905                                           TRUE, NULL);
906     if (!entry) {
907       SilcBuffer buffer;
908
909       /* If router did not find such Server ID in its lists then this must
910          be bogus client or some router in the net is buggy. */
911       if (server->server_type != SILC_SERVER)
912         goto out;
913
914       /* Statistics */
915       cmd->server->stat.commands_sent++;
916
917       /* entry isn't known so we IDENTIFY it. otherwise the
918          silc_server_command_motd won't know about it and tell
919          the client that there is no such server */
920       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
921       buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
922                                               ++server->cmd_ident, 5,
923                                               1, NULL, 0, 2, NULL, 0,
924                                               3, NULL, 0, 4, NULL, 0,
925                                               5, tmp, tmp_len);
926       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
927                               SILC_PACKET_COMMAND, 0, buffer->data,
928                               silc_buffer_len(buffer));
929       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
930                                   server->cmd_ident,
931                                   silc_server_command_reply_motd,
932                                   cmd);
933       silc_buffer_free(buffer);
934       return;
935     }
936   }
937
938   /* Get the motd */
939   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
940   if (tmp_len > 256)
941     tmp = NULL;
942
943   entry->motd = tmp;
944
945  out:
946   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
947  err:
948   silc_server_command_reply_free(cmd);
949
950   if (entry)
951     entry->motd = NULL;
952 }
953
954 /* Received reply for forwarded JOIN command. Router has created or joined
955    the client to the channel. We save some channel information locally
956    for future use. */
957
958 SILC_SERVER_CMD_REPLY_FUNC(join)
959 {
960   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
961   SilcServer server = cmd->server;
962   SilcIDCacheEntry cache = NULL;
963   SilcStatus status, error;
964   SilcID id, id2;
965   SilcChannelEntry entry;
966   SilcHmac hmac = NULL;
967   SilcUInt32 len, list_count;
968   char *channel_name, *channel_namec = NULL, *tmp;
969   SilcUInt32 mode, created;
970   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
971   SilcPublicKey founder_key = NULL;
972
973   COMMAND_CHECK_STATUS;
974
975   /* Get channel name */
976   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
977   if (!channel_name)
978     goto out;
979
980   /* Get channel ID */
981   if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
982     goto out;
983
984   /* Get client ID */
985   if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
986     goto out;
987
988   /* Get mode mask */
989   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
990   if (!tmp)
991     goto out;
992   SILC_GET32_MSB(mode, tmp);
993
994   /* Get created boolean value */
995   tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
996   if (!tmp)
997     goto out;
998   SILC_GET32_MSB(created, tmp);
999   if (created != 0 && created != 1)
1000     goto out;
1001
1002   /* Get channel key */
1003   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1004   if (tmp) {
1005     keyp = silc_buffer_alloc(len);
1006     silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1007     silc_buffer_put(keyp, tmp, len);
1008   }
1009
1010   /* Get hmac */
1011   tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1012   if (tmp) {
1013     if (!silc_hmac_alloc(tmp, NULL, &hmac))
1014       goto out;
1015   }
1016
1017   /* Get the list count */
1018   tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1019   if (!tmp)
1020     goto out;
1021   SILC_GET32_MSB(list_count, tmp);
1022
1023   /* Get Client ID list */
1024   tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1025   if (!tmp)
1026     goto out;
1027
1028   client_id_list = silc_buffer_alloc(len);
1029   silc_buffer_pull_tail(client_id_list, len);
1030   silc_buffer_put(client_id_list, tmp, len);
1031
1032   /* Get client mode list */
1033   tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1034   if (!tmp)
1035     goto out;
1036
1037   client_mode_list = silc_buffer_alloc(len);
1038   silc_buffer_pull_tail(client_mode_list, len);
1039   silc_buffer_put(client_mode_list, tmp, len);
1040
1041   /* Get founder key */
1042   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1043   if (tmp)
1044     silc_public_key_payload_decode(tmp, len, &founder_key);
1045
1046   /* See whether we already have the channel. */
1047   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1048                                           SILC_STRING_UTF8, 256, NULL);
1049   if (!channel_namec)
1050     goto out;
1051   entry = silc_idlist_find_channel_by_name(server->local_list,
1052                                            channel_namec, &cache);
1053   if (!entry) {
1054     /* Add new channel */
1055
1056     SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1057                     (created == 0 ? "existing" : "created"), channel_name,
1058                     silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1059
1060     /* If the channel is found from global list we must move it to the
1061        local list. */
1062     entry = silc_idlist_find_channel_by_name(server->global_list,
1063                                              channel_namec, &cache);
1064     if (entry)
1065       silc_idlist_del_channel(server->global_list, entry);
1066
1067     /* Add the channel to our local list. */
1068     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1069                                     SILC_CHANNEL_MODE_NONE,
1070                                     silc_id_dup(SILC_ID_GET_ID(id),
1071                                                 SILC_ID_CHANNEL),
1072                                     server->router, NULL, NULL, hmac);
1073     if (!entry)
1074       goto out;
1075
1076     hmac = NULL;
1077     server->stat.my_channels++;
1078     server->stat.channels++;
1079   } else {
1080     /* The entry exists. */
1081
1082     /* If ID has changed, then update it to the cache too. */
1083     if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1084       silc_idlist_replace_channel_id(server->local_list, entry->id,
1085                                      SILC_ID_GET_ID(id));
1086
1087     entry->disabled = FALSE;
1088
1089     /* Remove the founder auth data if the mode is not set but we have
1090        them in the entry */
1091     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1092       silc_pkcs_public_key_free(entry->founder_key);
1093       entry->founder_key = NULL;
1094     }
1095   }
1096
1097   if (founder_key) {
1098     if (entry->founder_key)
1099       silc_pkcs_public_key_free(entry->founder_key);
1100     entry->founder_key = founder_key;
1101     founder_key = NULL;
1102   }
1103
1104   if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1105     silc_free(entry->hmac_name);
1106     entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1107   }
1108
1109   /* Get the ban list */
1110   tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1111   if (tmp && len > 2) {
1112     SilcArgumentPayload iargs;
1113     SilcUInt16 iargc;
1114     SILC_GET16_MSB(iargc, tmp);
1115     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1116     if (iargs) {
1117       /* Delete old ban list */
1118       if (entry->ban_list)
1119         silc_hash_table_free(entry->ban_list);
1120       entry->ban_list =
1121         silc_hash_table_alloc(0, silc_hash_ptr,
1122                               NULL, NULL, NULL,
1123                               silc_server_inviteban_destruct, entry, TRUE);
1124
1125       /* Add new ban list */
1126       silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1127       silc_argument_payload_free(iargs);
1128     }
1129   }
1130
1131   /* Get the invite list */
1132   tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1133   if (tmp && len > 2) {
1134     SilcArgumentPayload iargs;
1135     SilcUInt16 iargc;
1136     SILC_GET16_MSB(iargc, tmp);
1137     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1138     if (iargs) {
1139       /* Delete old invite list */
1140       if (entry->invite_list)
1141         silc_hash_table_free(entry->invite_list);
1142       entry->invite_list =
1143         silc_hash_table_alloc(0, silc_hash_ptr,
1144                               NULL, NULL, NULL,
1145                               silc_server_inviteban_destruct, entry, TRUE);
1146
1147       /* Add new invite list */
1148       silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1149       silc_argument_payload_free(iargs);
1150     }
1151   }
1152
1153   /* Get the topic */
1154   tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1155   if (tmp) {
1156     silc_free(entry->topic);
1157     entry->topic = strdup(tmp);
1158   }
1159
1160   /* Get channel public key list */
1161   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1162   if (tmp && server->server_type != SILC_ROUTER)
1163     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1164
1165   /* The the user limit */
1166   tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1167   if (tmp && len == 4)
1168     SILC_GET32_MSB(entry->user_limit, tmp);
1169
1170   /* If channel was not created we know there is global users on the
1171      channel. */
1172   entry->global_users = (created == 0 ? TRUE : FALSE);
1173
1174   /* If channel was just created the mask must be zero */
1175   if (!entry->global_users && mode)
1176     mode = 0;
1177
1178   /* Save channel mode */
1179   entry->mode = mode;
1180
1181   /* Save channel key */
1182   if (keyp) {
1183     if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1184       silc_server_save_channel_key(server, keyp, entry);
1185     silc_buffer_free(keyp);
1186   }
1187
1188   /* Save the users to the channel */
1189   silc_server_save_users_on_channel(server, cmd->sock, entry,
1190                                     SILC_ID_GET_ID(id2), client_id_list,
1191                                     client_mode_list, list_count);
1192   entry->users_resolved = TRUE;
1193
1194  out:
1195   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1196  err:
1197   silc_free(channel_namec);
1198   if (hmac)
1199     silc_hmac_free(hmac);
1200   silc_server_command_reply_free(cmd);
1201
1202   silc_pkcs_public_key_free(founder_key);
1203   if (client_id_list)
1204     silc_buffer_free(client_id_list);
1205   if (client_mode_list)
1206     silc_buffer_free(client_mode_list);
1207 }
1208
1209 /* Received reply to STATS command.  */
1210
1211 SILC_SERVER_CMD_REPLY_FUNC(stats)
1212 {
1213   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1214   SilcServer server = cmd->server;
1215   SilcStatus status, error;
1216   unsigned char *tmp;
1217   SilcUInt32 tmp_len;
1218   SilcBufferStruct buf;
1219
1220   COMMAND_CHECK_STATUS;
1221
1222   /* Get statistics structure */
1223   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1224   if (server->server_type != SILC_ROUTER && tmp) {
1225     silc_buffer_set(&buf, tmp, tmp_len);
1226     silc_buffer_unformat(&buf,
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(NULL),
1232                          SILC_STR_UI_INT(NULL),
1233                          SILC_STR_UI_INT(&server->stat.cell_clients),
1234                          SILC_STR_UI_INT(&server->stat.cell_channels),
1235                          SILC_STR_UI_INT(&server->stat.cell_servers),
1236                          SILC_STR_UI_INT(&server->stat.clients),
1237                          SILC_STR_UI_INT(&server->stat.channels),
1238                          SILC_STR_UI_INT(&server->stat.servers),
1239                          SILC_STR_UI_INT(&server->stat.routers),
1240                          SILC_STR_UI_INT(&server->stat.server_ops),
1241                          SILC_STR_UI_INT(&server->stat.router_ops),
1242                          SILC_STR_END);
1243   }
1244
1245  out:
1246   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1247  err:
1248   silc_server_command_reply_free(cmd);
1249 }
1250
1251 SILC_SERVER_CMD_REPLY_FUNC(users)
1252 {
1253   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1254   SilcServer server = cmd->server;
1255   SilcStatus status, error;
1256   SilcChannelEntry channel;
1257   SilcID id;
1258   SilcBuffer client_id_list;
1259   SilcBuffer client_mode_list;
1260   unsigned char *tmp;
1261   SilcUInt32 tmp_len;
1262   SilcUInt32 list_count;
1263
1264   COMMAND_CHECK_STATUS;
1265
1266   /* Get channel ID */
1267   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1268     goto out;
1269
1270   /* Get channel entry */
1271   channel = silc_idlist_find_channel_by_id(server->local_list,
1272                                            SILC_ID_GET_ID(id), NULL);
1273   if (!channel) {
1274     channel = silc_idlist_find_channel_by_id(server->global_list,
1275                                              SILC_ID_GET_ID(id), NULL);
1276     if (!channel) {
1277       SilcBuffer idp;
1278
1279       if (server->server_type != SILC_SERVER)
1280         goto out;
1281
1282       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1283       silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1284                                SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1285                                1, 5, idp->data, silc_buffer_len(idp));
1286       silc_buffer_free(idp);
1287
1288       /* Register pending command callback. After we've received the channel
1289          information we will reprocess this command reply by re-calling this
1290          USERS command reply callback. */
1291       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1292                                   server->cmd_ident,
1293                                   silc_server_command_reply_users, cmd);
1294       return;
1295     }
1296   }
1297
1298   /* Get the list count */
1299   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1300   if (!tmp)
1301     goto out;
1302   SILC_GET32_MSB(list_count, tmp);
1303
1304   /* Get Client ID list */
1305   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1306   if (!tmp)
1307     goto out;
1308
1309   client_id_list = silc_buffer_alloc(tmp_len);
1310   silc_buffer_pull_tail(client_id_list, tmp_len);
1311   silc_buffer_put(client_id_list, tmp, tmp_len);
1312
1313   /* Get client mode list */
1314   tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1315   if (!tmp)
1316     goto out;
1317
1318   client_mode_list = silc_buffer_alloc(tmp_len);
1319   silc_buffer_pull_tail(client_mode_list, tmp_len);
1320   silc_buffer_put(client_mode_list, tmp, tmp_len);
1321
1322   /* Save the users to the channel */
1323   silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1324                                     client_id_list, client_mode_list,
1325                                     list_count);
1326
1327   channel->global_users = silc_server_channel_has_global(channel);
1328   channel->users_resolved = TRUE;
1329
1330   silc_buffer_free(client_id_list);
1331   silc_buffer_free(client_mode_list);
1332
1333  out:
1334   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1335  err:
1336   silc_server_command_reply_free(cmd);
1337 }
1338
1339 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1340 {
1341   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1342   SilcServer server = cmd->server;
1343   SilcStatus status, error;
1344   SilcClientEntry client = NULL;
1345   SilcServerEntry server_entry = NULL;
1346   SilcClientID client_id;
1347   SilcServerID server_id;
1348   unsigned char *tmp;
1349   SilcUInt32 len;
1350   SilcIDPayload idp = NULL;
1351   SilcIdType id_type;
1352   SilcPublicKey public_key = NULL;
1353
1354   COMMAND_CHECK_STATUS;
1355
1356   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1357   if (!tmp)
1358     goto out;
1359   idp = silc_id_payload_parse(tmp, len);
1360   if (!idp)
1361     goto out;
1362
1363   /* Get the public key payload */
1364   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1365   if (!tmp)
1366     goto out;
1367
1368   /* Decode the public key payload */
1369   if (!silc_public_key_payload_decode(tmp, len, &public_key))
1370     goto out;
1371
1372   id_type = silc_id_payload_get_type(idp);
1373   if (id_type == SILC_ID_CLIENT) {
1374     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1375
1376     client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1377                                            TRUE, NULL);
1378     if (!client) {
1379       client = silc_idlist_find_client_by_id(server->global_list,
1380                                              &client_id, TRUE, NULL);
1381       if (!client)
1382         goto out;
1383     }
1384
1385     if (!client->data.public_key) {
1386       /* Add client's public key to repository */
1387       if (!silc_server_get_public_key_by_client(server, client, NULL))
1388         silc_skr_add_public_key_simple(server->repository,
1389                                        public_key,
1390                                        SILC_SKR_USAGE_IDENTIFICATION,
1391                                        client, NULL);
1392       client->data.public_key = public_key;
1393       public_key = NULL;
1394     }
1395   } else if (id_type == SILC_ID_SERVER) {
1396     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1397
1398     server_entry = silc_idlist_find_server_by_id(server->local_list,
1399                                                  &server_id, TRUE, NULL);
1400     if (!server_entry) {
1401       server_entry = silc_idlist_find_server_by_id(server->global_list,
1402                                                    &server_id, TRUE, NULL);
1403       if (!server_entry)
1404         goto out;
1405     }
1406
1407     server_entry->data.public_key = public_key;
1408     public_key = NULL;
1409   } else {
1410     goto out;
1411   }
1412
1413  out:
1414   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1415   if (idp)
1416     silc_id_payload_free(idp);
1417   if (public_key)
1418     silc_pkcs_public_key_free(public_key);
1419  err:
1420   silc_server_command_reply_free(cmd);
1421 }
1422
1423 SILC_SERVER_CMD_REPLY_FUNC(list)
1424 {
1425   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1426   SilcServer server = cmd->server;
1427   SilcStatus status, error;
1428   SilcID id;
1429   SilcChannelEntry channel;
1430   SilcIDCacheEntry cache;
1431   unsigned char *tmp, *name, *namec = NULL, *topic;
1432   SilcUInt32 usercount = 0;
1433   SilcBool global_list = FALSE;
1434
1435   COMMAND_CHECK_STATUS;
1436
1437   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1438     goto out;
1439
1440   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1441   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1442   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1443   if (tmp)
1444     SILC_GET32_MSB(usercount, tmp);
1445
1446   namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1447                                   256, NULL);
1448   if (!namec)
1449     goto out;
1450
1451   /* Add the channel entry if we do not have it already */
1452   channel = silc_idlist_find_channel_by_name(server->local_list,
1453                                              namec, &cache);
1454   if (!channel) {
1455     channel = silc_idlist_find_channel_by_name(server->global_list,
1456                                                namec, &cache);
1457     global_list = TRUE;
1458   }
1459   if (!channel) {
1460     /* If router did not find such channel in its lists then this must
1461        be bogus channel or some router in the net is buggy. */
1462     if (server->server_type != SILC_SERVER)
1463       goto out;
1464
1465     channel = silc_idlist_add_channel(server->global_list, strdup(name),
1466                                       SILC_CHANNEL_MODE_NONE,
1467                                       silc_id_dup(SILC_ID_GET_ID(id),
1468                                                   SILC_ID_CHANNEL),
1469                                       server->router, NULL, NULL, NULL);
1470     if (!channel)
1471       goto out;
1472   }
1473
1474   channel->user_count = usercount;
1475
1476   if (topic) {
1477     silc_free(channel->topic);
1478     channel->topic = strdup(topic);
1479   }
1480
1481   /* Pending callbacks are not executed if this was an list entry */
1482   if (status != SILC_STATUS_OK &&
1483       status != SILC_STATUS_LIST_END) {
1484     silc_server_command_reply_free(cmd);
1485     return;
1486   }
1487
1488  out:
1489   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1490  err:
1491   silc_free(namec);
1492   silc_server_command_reply_free(cmd);
1493 }
1494
1495 SILC_SERVER_CMD_REPLY_FUNC(watch)
1496 {
1497   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1498   SilcStatus status, error;
1499
1500   COMMAND_CHECK_STATUS;
1501
1502  out:
1503   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1504  err:
1505   silc_server_command_reply_free(cmd);
1506 }
1507
1508 SILC_SERVER_CMD_REPLY_FUNC(ping)
1509 {
1510   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1511   SilcStatus status, error;
1512
1513   COMMAND_CHECK_STATUS;
1514
1515  out:
1516   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1517  err:
1518   silc_server_command_reply_free(cmd);
1519 }