Removed HTTP server libary, it's available in SRT now
[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   if (founder_key)
1203     silc_pkcs_public_key_free(founder_key);
1204   if (client_id_list)
1205     silc_buffer_free(client_id_list);
1206   if (client_mode_list)
1207     silc_buffer_free(client_mode_list);
1208 }
1209
1210 /* Received reply to STATS command.  */
1211
1212 SILC_SERVER_CMD_REPLY_FUNC(stats)
1213 {
1214   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1215   SilcServer server = cmd->server;
1216   SilcStatus status, error;
1217   unsigned char *tmp;
1218   SilcUInt32 tmp_len;
1219   SilcBufferStruct buf;
1220
1221   COMMAND_CHECK_STATUS;
1222
1223   /* Get statistics structure */
1224   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1225   if (server->server_type != SILC_ROUTER && tmp) {
1226     silc_buffer_set(&buf, tmp, tmp_len);
1227     silc_buffer_unformat(&buf,
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(NULL),
1234                          SILC_STR_UI_INT(&server->stat.cell_clients),
1235                          SILC_STR_UI_INT(&server->stat.cell_channels),
1236                          SILC_STR_UI_INT(&server->stat.cell_servers),
1237                          SILC_STR_UI_INT(&server->stat.clients),
1238                          SILC_STR_UI_INT(&server->stat.channels),
1239                          SILC_STR_UI_INT(&server->stat.servers),
1240                          SILC_STR_UI_INT(&server->stat.routers),
1241                          SILC_STR_UI_INT(&server->stat.server_ops),
1242                          SILC_STR_UI_INT(&server->stat.router_ops),
1243                          SILC_STR_END);
1244   }
1245
1246  out:
1247   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1248  err:
1249   silc_server_command_reply_free(cmd);
1250 }
1251
1252 SILC_SERVER_CMD_REPLY_FUNC(users)
1253 {
1254   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1255   SilcServer server = cmd->server;
1256   SilcStatus status, error;
1257   SilcChannelEntry channel;
1258   SilcID id;
1259   SilcBuffer client_id_list;
1260   SilcBuffer client_mode_list;
1261   unsigned char *tmp;
1262   SilcUInt32 tmp_len;
1263   SilcUInt32 list_count;
1264
1265   COMMAND_CHECK_STATUS;
1266
1267   /* Get channel ID */
1268   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1269     goto out;
1270
1271   /* Get channel entry */
1272   channel = silc_idlist_find_channel_by_id(server->local_list,
1273                                            SILC_ID_GET_ID(id), NULL);
1274   if (!channel) {
1275     channel = silc_idlist_find_channel_by_id(server->global_list,
1276                                              SILC_ID_GET_ID(id), NULL);
1277     if (!channel) {
1278       SilcBuffer idp;
1279
1280       if (server->server_type != SILC_SERVER)
1281         goto out;
1282
1283       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1284       silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1285                                SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1286                                1, 5, idp->data, silc_buffer_len(idp));
1287       silc_buffer_free(idp);
1288
1289       /* Register pending command callback. After we've received the channel
1290          information we will reprocess this command reply by re-calling this
1291          USERS command reply callback. */
1292       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1293                                   server->cmd_ident,
1294                                   silc_server_command_reply_users, cmd);
1295       return;
1296     }
1297   }
1298
1299   /* Get the list count */
1300   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1301   if (!tmp)
1302     goto out;
1303   SILC_GET32_MSB(list_count, tmp);
1304
1305   /* Get Client ID list */
1306   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1307   if (!tmp)
1308     goto out;
1309
1310   client_id_list = silc_buffer_alloc(tmp_len);
1311   silc_buffer_pull_tail(client_id_list, tmp_len);
1312   silc_buffer_put(client_id_list, tmp, tmp_len);
1313
1314   /* Get client mode list */
1315   tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1316   if (!tmp)
1317     goto out;
1318
1319   client_mode_list = silc_buffer_alloc(tmp_len);
1320   silc_buffer_pull_tail(client_mode_list, tmp_len);
1321   silc_buffer_put(client_mode_list, tmp, tmp_len);
1322
1323   /* Save the users to the channel */
1324   silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1325                                     client_id_list, client_mode_list,
1326                                     list_count);
1327
1328   channel->global_users = silc_server_channel_has_global(channel);
1329   channel->users_resolved = TRUE;
1330
1331   silc_buffer_free(client_id_list);
1332   silc_buffer_free(client_mode_list);
1333
1334  out:
1335   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1336  err:
1337   silc_server_command_reply_free(cmd);
1338 }
1339
1340 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1341 {
1342   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1343   SilcServer server = cmd->server;
1344   SilcStatus status, error;
1345   SilcClientEntry client = NULL;
1346   SilcServerEntry server_entry = NULL;
1347   SilcClientID client_id;
1348   SilcServerID server_id;
1349   unsigned char *tmp;
1350   SilcUInt32 len;
1351   SilcIDPayload idp = NULL;
1352   SilcIdType id_type;
1353   SilcPublicKey public_key = NULL;
1354
1355   COMMAND_CHECK_STATUS;
1356
1357   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1358   if (!tmp)
1359     goto out;
1360   idp = silc_id_payload_parse(tmp, len);
1361   if (!idp)
1362     goto out;
1363
1364   /* Get the public key payload */
1365   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1366   if (!tmp)
1367     goto out;
1368
1369   /* Decode the public key payload */
1370   if (!silc_public_key_payload_decode(tmp, len, &public_key))
1371     goto out;
1372
1373   id_type = silc_id_payload_get_type(idp);
1374   if (id_type == SILC_ID_CLIENT) {
1375     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1376
1377     client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1378                                            TRUE, NULL);
1379     if (!client) {
1380       client = silc_idlist_find_client_by_id(server->global_list,
1381                                              &client_id, TRUE, NULL);
1382       if (!client)
1383         goto out;
1384     }
1385
1386     if (!client->data.public_key) {
1387       /* Add client's public key to repository */
1388       if (!silc_server_get_public_key_by_client(server, client, NULL))
1389         silc_skr_add_public_key_simple(server->repository,
1390                                        public_key,
1391                                        SILC_SKR_USAGE_IDENTIFICATION,
1392                                        client, NULL);
1393       client->data.public_key = public_key;
1394       public_key = NULL;
1395     }
1396   } else if (id_type == SILC_ID_SERVER) {
1397     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1398
1399     server_entry = silc_idlist_find_server_by_id(server->local_list,
1400                                                  &server_id, TRUE, NULL);
1401     if (!server_entry) {
1402       server_entry = silc_idlist_find_server_by_id(server->global_list,
1403                                                    &server_id, TRUE, NULL);
1404       if (!server_entry)
1405         goto out;
1406     }
1407
1408     server_entry->data.public_key = public_key;
1409     public_key = NULL;
1410   } else {
1411     goto out;
1412   }
1413
1414  out:
1415   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1416   if (idp)
1417     silc_id_payload_free(idp);
1418   if (public_key)
1419     silc_pkcs_public_key_free(public_key);
1420  err:
1421   silc_server_command_reply_free(cmd);
1422 }
1423
1424 SILC_SERVER_CMD_REPLY_FUNC(list)
1425 {
1426   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1427   SilcServer server = cmd->server;
1428   SilcStatus status, error;
1429   SilcID id;
1430   SilcChannelEntry channel;
1431   SilcIDCacheEntry cache;
1432   unsigned char *tmp, *name, *namec = NULL, *topic;
1433   SilcUInt32 usercount = 0;
1434   SilcBool global_list = FALSE;
1435
1436   COMMAND_CHECK_STATUS;
1437
1438   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1439     goto out;
1440
1441   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1442   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1443   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1444   if (tmp)
1445     SILC_GET32_MSB(usercount, tmp);
1446
1447   namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1448                                   256, NULL);
1449   if (!namec)
1450     goto out;
1451
1452   /* Add the channel entry if we do not have it already */
1453   channel = silc_idlist_find_channel_by_name(server->local_list,
1454                                              namec, &cache);
1455   if (!channel) {
1456     channel = silc_idlist_find_channel_by_name(server->global_list,
1457                                                namec, &cache);
1458     global_list = TRUE;
1459   }
1460   if (!channel) {
1461     /* If router did not find such channel in its lists then this must
1462        be bogus channel or some router in the net is buggy. */
1463     if (server->server_type != SILC_SERVER)
1464       goto out;
1465
1466     channel = silc_idlist_add_channel(server->global_list, strdup(name),
1467                                       SILC_CHANNEL_MODE_NONE,
1468                                       silc_id_dup(SILC_ID_GET_ID(id),
1469                                                   SILC_ID_CHANNEL),
1470                                       server->router, NULL, NULL, NULL);
1471     if (!channel)
1472       goto out;
1473   }
1474
1475   channel->user_count = usercount;
1476
1477   if (topic) {
1478     silc_free(channel->topic);
1479     channel->topic = strdup(topic);
1480   }
1481
1482   /* Pending callbacks are not executed if this was an list entry */
1483   if (status != SILC_STATUS_OK &&
1484       status != SILC_STATUS_LIST_END) {
1485     silc_server_command_reply_free(cmd);
1486     return;
1487   }
1488
1489  out:
1490   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1491  err:
1492   silc_free(namec);
1493   silc_server_command_reply_free(cmd);
1494 }
1495
1496 SILC_SERVER_CMD_REPLY_FUNC(watch)
1497 {
1498   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1499   SilcStatus status, error;
1500
1501   COMMAND_CHECK_STATUS;
1502
1503  out:
1504   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1505  err:
1506   silc_server_command_reply_free(cmd);
1507 }
1508
1509 SILC_SERVER_CMD_REPLY_FUNC(ping)
1510 {
1511   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1512   SilcStatus status, error;
1513
1514   COMMAND_CHECK_STATUS;
1515
1516  out:
1517   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1518  err:
1519   silc_server_command_reply_free(cmd);
1520 }