Merge commit 'origin/silc.1.1.branch'
[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_dlist_del(server->expired_clients, client);
156       silc_idlist_del_data(client);
157       silc_idlist_del_client(server->global_list, client);
158     }
159   }
160 }
161
162 /* Caches the received WHOIS information. */
163
164 static char
165 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
166 {
167   SilcServer server = cmd->server;
168   unsigned char *id_data, *umodes;
169   char *nickname, *username, *realname, *tmp;
170   unsigned char *fingerprint;
171   SilcID id;
172   SilcClientEntry client;
173   char global = FALSE;
174   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
175   SilcUInt32 mode = 0, len, len2, id_len, flen;
176   const char *hostname, *ip;
177
178   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
179                               NULL, &hostname, &ip, NULL);
180
181   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
182   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
183   username = silc_argument_get_arg_type(cmd->args, 4, &len);
184   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
185   if (!id_data || !nickname || !username || !realname)
186     return FALSE;
187
188   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
189   if (tmp)
190     SILC_GET32_MSB(mode, tmp);
191
192   if (!silc_id_payload_parse_id(id_data, id_len, &id))
193     return FALSE;
194
195   fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
196
197   /* Check if we have this client cached already. */
198
199   client = silc_idlist_find_client_by_id(server->local_list,
200                                          SILC_ID_GET_ID(id),
201                                          FALSE, NULL);
202   if (!client) {
203     client = silc_idlist_find_client_by_id(server->global_list,
204                                            SILC_ID_GET_ID(id),
205                                            FALSE, NULL);
206     global = TRUE;
207   }
208
209   if (!client) {
210     /* If router did not find such Client ID in its lists then this must
211        be bogus client or some router in the net is buggy. */
212     if (server->server_type != SILC_SERVER)
213       return FALSE;
214
215     /* Take hostname out of nick string if it includes it. */
216     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
217                         sizeof(servername));
218
219     /* We don't have that client anywhere, add it. The client is added
220        to global list since server didn't have it in the lists so it must be
221        global. This will check for valid nickname and username strings. */
222     client = silc_idlist_add_client(server->global_list,
223                                     strdup(nick), username,
224                                     strdup(realname),
225                                     silc_id_dup(SILC_ID_GET_ID(id),
226                                                 SILC_ID_CLIENT),
227                                     silc_packet_get_context(cmd->sock),
228                                     NULL);
229     if (!client) {
230       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
231       return FALSE;
232     }
233
234     client->data.status |=
235       (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
236     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
237     client->mode = mode;
238     client->servername = servername[0] ? strdup(servername) : NULL;
239   } else {
240     /* We have the client already, update the data */
241
242     SILC_LOG_DEBUG(("Updating client data"));
243
244     /* Check nickname */
245     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
246                         sizeof(servername));
247     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
248                                      128, NULL);
249     if (!nickname) {
250       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
251                       "from %s",
252                       hostname ? hostname : "", nick));
253       return FALSE;
254     }
255
256     /* Check username */
257     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
258     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
259       SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
260                       "from %s",
261                       hostname ? hostname : "", tmp));
262       return FALSE;
263     }
264
265     /* Update entry */
266     silc_idcache_update_by_context(global ? server->global_list->clients :
267                                    server->local_list->clients, client, NULL,
268                                    nickname, TRUE);
269
270     silc_free(client->nickname);
271     silc_free(client->username);
272     silc_free(client->userinfo);
273     silc_free(client->servername);
274
275     client->nickname = strdup(nick);
276     client->username = strdup(username);
277     client->userinfo = strdup(realname);
278     client->servername = servername[0] ? strdup(servername) : NULL;
279     client->mode = mode;
280     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
281     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
282   }
283
284   /* Save channel list if it was sent to us */
285   if (server->server_type == SILC_SERVER) {
286     tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
287     umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
288     if (tmp && umodes) {
289       SilcBufferStruct channels_buf, umodes_buf;
290       silc_buffer_set(&channels_buf, tmp, len);
291       silc_buffer_set(&umodes_buf, umodes, len2);
292       silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
293                                      &umodes_buf);
294     } else {
295       silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
296     }
297   }
298
299   if (fingerprint && flen == sizeof(client->data.fingerprint))
300     memcpy(client->data.fingerprint, fingerprint, flen);
301
302   /* Take Requested Attributes if set. */
303   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
304   if (tmp) {
305     silc_free(client->attrs);
306     client->attrs = silc_memdup(tmp, len);
307     client->attrs_len = len;
308
309     /* Try to take public key from attributes if present and we don't have
310        the key already.  Do this only on normal server.  Routers do GETKEY
311        for all clients anyway. */
312     if (server->server_type != SILC_ROUTER && !client->data.public_key) {
313       SilcAttributePayload attr;
314       SilcAttributeObjPk pk;
315       unsigned char f[SILC_HASH_MAXLEN];
316       SilcDList attrs = silc_attribute_payload_parse(tmp, len);
317
318       SILC_LOG_DEBUG(("Take client public key from attributes"));
319
320       if (attrs) {
321         silc_dlist_start(attrs);
322         while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
323           if (silc_attribute_get_attribute(attr) ==
324               SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
325
326             if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
327               continue;
328
329             /* Take only SILC public keys */
330             if (strcmp(pk.type, "silc-rsa")) {
331               silc_free(pk.type);
332               silc_free(pk.data);
333               continue;
334             }
335
336             /* Verify that the server provided fingerprint matches the key */
337             silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
338             if (memcmp(f, client->data.fingerprint, sizeof(f))) {
339               silc_free(pk.type);
340               silc_free(pk.data);
341               continue;
342             }
343
344             /* Save the public key. */
345             if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
346                                             pk.data, pk.data_len,
347                                             &client->data.public_key)) {
348               silc_free(pk.type);
349               silc_free(pk.data);
350               continue;
351             }
352
353             SILC_LOG_DEBUG(("Saved client public key from attributes"));
354
355             /* Add client's public key to repository */
356             if (!silc_server_get_public_key_by_client(server, client, NULL))
357               silc_skr_add_public_key_simple(server->repository,
358                                              client->data.public_key,
359                                              SILC_SKR_USAGE_IDENTIFICATION,
360                                              client, NULL);
361
362             silc_free(pk.type);
363             silc_free(pk.data);
364             break;
365           }
366         }
367
368         silc_attribute_payload_list_free(attrs);
369       }
370     }
371   }
372
373   return TRUE;
374 }
375
376 /* Handle requested attributes reply in WHOIS from client */
377
378 static char
379 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
380 {
381   unsigned char *tmp;
382   SilcUInt32 len;
383   SilcClientEntry client = silc_packet_get_context(cmd->sock);
384
385   /* Take Requested Attributes if set. */
386   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
387   if (tmp && client) {
388     silc_free(client->attrs);
389     client->attrs = silc_memdup(tmp, len);
390     client->attrs_len = len;
391   }
392
393   client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
394
395   return TRUE;
396 }
397
398 /* Reiceved reply for WHOIS command. We sent the whois request to our
399    primary router, if we are normal server, and thus has now received reply
400    to the command. We will figure out what client originally sent us the
401    command and will send the reply to it.  If we are router we will figure
402    out who server sent us the command and send reply to that one. */
403
404 SILC_SERVER_CMD_REPLY_FUNC(whois)
405 {
406   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
407   SilcIDListData idata = silc_packet_get_context(cmd->sock);
408   SilcStatus status, error;
409
410   COMMAND_CHECK_STATUS;
411
412   if (idata->conn_type != SILC_CONN_CLIENT) {
413     if (!silc_server_command_reply_whois_save(cmd))
414       goto out;
415   } else {
416     if (!silc_server_command_reply_whois_save_client(cmd))
417       goto out;
418   }
419
420   /* Pending callbacks are not executed if this was an list entry */
421   if (status != SILC_STATUS_OK &&
422       status != SILC_STATUS_LIST_END) {
423     silc_server_command_reply_free(cmd);
424     return;
425   }
426
427  out:
428   silc_server_command_process_error(cmd, error);
429   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
430   silc_server_command_reply_free(cmd);
431   return;
432
433  err:
434   silc_server_command_process_error(cmd, error);
435   silc_server_command_reply_free(cmd);
436 }
437
438 /* Caches the received WHOWAS information for a short period of time. */
439
440 static char
441 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
442 {
443   SilcServer server = cmd->server;
444   SilcUInt32 len, id_len;
445   unsigned char *id_data;
446   char *nickname, *username, *realname;
447   SilcID id;
448   SilcClientEntry client;
449   SilcIDCacheEntry cache = NULL;
450   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
451   int global = FALSE;
452   const char *hostname, *ip;
453
454   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
455                               NULL, &hostname, &ip, NULL);
456
457   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
458   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
459   username = silc_argument_get_arg_type(cmd->args, 4, &len);
460   if (!id_data || !nickname || !username)
461     return FALSE;
462
463   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
464
465   if (!silc_id_payload_parse_id(id_data, id_len, &id))
466     return FALSE;
467
468   /* Check if we have this client cached already. */
469
470   client = silc_idlist_find_client_by_id(server->local_list,
471                                          SILC_ID_GET_ID(id),
472                                          FALSE, &cache);
473   if (!client) {
474     client = silc_idlist_find_client_by_id(server->global_list,
475                                            SILC_ID_GET_ID(id),
476                                            FALSE, &cache);
477     global = TRUE;
478   }
479
480   if (!client) {
481     /* If router did not find such Client ID in its lists then this must
482        be bogus client or some router in the net is buggy. */
483     if (server->server_type != SILC_SERVER)
484       return FALSE;
485
486     /* Take hostname out of nick string if it includes it. */
487     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
488                         sizeof(servername));
489
490     /* We don't have that client anywhere, add it. The client is added
491        to global list since server didn't have it in the lists so it must be
492        global. */
493     client = silc_idlist_add_client(server->global_list,
494                                     strdup(nick), username,
495                                     strdup(realname),
496                                     silc_id_dup(SILC_ID_GET_ID(id),
497                                                 SILC_ID_CLIENT),
498                                     silc_packet_get_context(cmd->sock), NULL);
499     if (!client) {
500       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
501       return FALSE;
502     }
503
504     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
505     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
506     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
507     client->servername = servername[0] ? strdup(servername) : NULL;
508   } else {
509     /* We have the client already, update the data */
510
511     /* Check nickname */
512     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
513                         sizeof(servername));
514     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
515                                      128, NULL);
516     if (!nickname) {
517       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
518                       "from %s",
519                       nick, hostname ? hostname : ""));
520       return FALSE;
521     }
522
523     /* Check username */
524     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
525     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
526       return FALSE;
527
528     silc_free(client->nickname);
529     silc_free(client->username);
530     silc_free(client->servername);
531
532     client->nickname = strdup(nick);
533     client->username = strdup(username);
534     client->servername = servername[0] ? strdup(servername) : NULL;
535     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
536     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
537     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
538
539     /* Update cache entry */
540     silc_idcache_update_by_context(global ? server->global_list->clients :
541                                    server->local_list->clients, client, NULL,
542                                    nickname, TRUE);
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     client = silc_idlist_find_client_by_id(server->global_list, client->id,
549                                            FALSE, &cache);
550     if (client && !silc_hash_table_count(client->channels)) {
551       client->data.created = silc_time();
552       silc_dlist_del(server->expired_clients, client);
553       silc_dlist_add(server->expired_clients, client);
554     }
555   }
556
557   return TRUE;
558 }
559
560 /* Received reply for WHOWAS command. Cache the client information only for
561    a short period of time. */
562
563 SILC_SERVER_CMD_REPLY_FUNC(whowas)
564 {
565   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
566   SilcStatus status, error;
567
568   COMMAND_CHECK_STATUS;
569
570   if (!silc_server_command_reply_whowas_save(cmd))
571     goto out;
572
573   /* Pending callbacks are not executed if this was an list entry */
574   if (status != SILC_STATUS_OK &&
575       status != SILC_STATUS_LIST_END) {
576     silc_server_command_reply_free(cmd);
577     return;
578   }
579
580  out:
581   silc_server_command_process_error(cmd, error);
582   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
583   silc_server_command_reply_free(cmd);
584   return;
585
586  err:
587   silc_server_command_process_error(cmd, error);
588   silc_server_command_reply_free(cmd);
589 }
590
591 /* Caches the received IDENTIFY information. */
592
593 static char
594 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
595 {
596   SilcServer server = cmd->server;
597   SilcUInt32 len, id_len;
598   unsigned char *id_data;
599   char *name, *info;
600   SilcClientID client_id;
601   SilcServerID server_id;
602   SilcChannelID*channel_id;
603   SilcClientEntry client;
604   SilcServerEntry server_entry;
605   SilcChannelEntry channel;
606   char global = FALSE;
607   char nick[128 + 1];
608   SilcIDPayload idp = NULL;
609   SilcIdType id_type;
610
611   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
612   if (!id_data)
613     return FALSE;
614   idp = silc_id_payload_parse(id_data, id_len);
615   if (!idp)
616     return FALSE;
617
618   name = silc_argument_get_arg_type(cmd->args, 3, &len);
619   info = silc_argument_get_arg_type(cmd->args, 4, &len);
620
621   id_type = silc_id_payload_get_type(idp);
622
623   switch (id_type) {
624   case SILC_ID_CLIENT:
625     if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
626       goto error;
627
628     SILC_LOG_DEBUG(("Received client information"));
629
630     client = silc_idlist_find_client_by_id(server->local_list,
631                                            &client_id, FALSE, NULL);
632     if (!client) {
633       client = silc_idlist_find_client_by_id(server->global_list, &client_id,
634                                              FALSE, NULL);
635       global = TRUE;
636     }
637     if (!client) {
638       /* If router did not find such Client ID in its lists then this must
639          be bogus client or some router in the net is buggy. */
640       if (server->server_type != SILC_SERVER)
641         goto error;
642
643       /* Take nickname */
644       if (name)
645         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
646
647       /* We don't have that client anywhere, add it. The client is added
648          to global list since server didn't have it in the lists so it must be
649          global. */
650       client = silc_idlist_add_client(server->global_list,
651                                       nick[0] ? nick : NULL, info, NULL,
652                                       silc_id_dup(&client_id, SILC_ID_CLIENT),
653                                       silc_packet_get_context(cmd->sock),
654                                       NULL);
655       if (!client) {
656         SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
657         goto error;
658       }
659
660       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
661       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
662       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
663     } else {
664       /* We have the client already, update the data */
665
666       SILC_LOG_DEBUG(("Updating client data"));
667
668       /* Take nickname */
669       if (name) {
670         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
671
672         /* Check nickname */
673         name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
674                                      128, NULL);
675         if (!name) {
676           SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
677                           "reply ", nick));
678           return FALSE;
679         }
680
681         silc_free(client->nickname);
682         client->nickname = strdup(nick);
683
684         /* Update the context */
685         silc_idcache_update_by_context(global ? server->global_list->clients :
686                                        server->local_list->clients, client,
687                                        NULL, name, TRUE);
688       }
689
690       if (info) {
691         silc_free(client->username);
692         client->username = strdup(info);
693       }
694
695       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
696       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
697     }
698
699     break;
700
701   case SILC_ID_SERVER:
702     if (!name)
703       goto error;
704
705     if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
706       goto error;
707
708     SILC_LOG_DEBUG(("Received server information"));
709
710     server_entry = silc_idlist_find_server_by_id(server->local_list,
711                                                  &server_id, FALSE, NULL);
712     if (!server_entry)
713       server_entry = silc_idlist_find_server_by_id(server->global_list,
714                                                    &server_id, FALSE, NULL);
715     if (!server_entry) {
716       /* If router did not find such Server ID in its lists then this must
717          be bogus server or some router in the net is buggy. */
718       if (server->server_type != SILC_SERVER)
719         goto error;
720
721       /* We don't have that server anywhere, add it. */
722       server_entry = silc_idlist_add_server(server->global_list,
723                                             strdup(name), 0,
724                                             silc_id_dup(&server_id,
725                                                         SILC_ID_SERVER),
726                                             server->router,
727                                             SILC_PRIMARY_ROUTE(server));
728       if (!server_entry)
729         goto error;
730
731       server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
732       server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
733       server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
734     }
735
736     break;
737
738   case SILC_ID_CHANNEL:
739     if (!name)
740       goto error;
741
742     if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
743       goto error;
744
745     SILC_LOG_DEBUG(("Received channel information"));
746
747     /* Check channel name */
748     info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
749                                    256, NULL);
750     if (!info)
751       goto error;
752
753     channel = silc_idlist_find_channel_by_name(server->local_list,
754                                                info, NULL);
755     if (!channel)
756       channel = silc_idlist_find_channel_by_name(server->global_list,
757                                                  info, NULL);
758     if (!channel) {
759       /* If router did not find such Channel ID in its lists then this must
760          be bogus channel or some router in the net is buggy. */
761       if (server->server_type != SILC_SERVER) {
762         silc_free(info);
763         goto error;
764       }
765
766       /* We don't have that channel anywhere, add it. */
767       channel = silc_idlist_add_channel(server->global_list, strdup(name),
768                                         SILC_CHANNEL_MODE_NONE,
769                                         silc_id_dup(&channel_id,
770                                                     SILC_ID_CHANNEL),
771                                         server->router, NULL, NULL, 0);
772       if (!channel) {
773         silc_free(info);
774         goto error;
775       }
776       silc_free(info);
777     }
778
779     break;
780   }
781
782   silc_id_payload_free(idp);
783   return TRUE;
784
785  error:
786   silc_id_payload_free(idp);
787   return FALSE;
788 }
789
790 /* Received reply for forwarded IDENTIFY command. We have received the
791    requested identify information now and we will cache it. After this we
792    will call the pending command so that the requestee gets the information
793    after all. */
794
795 SILC_SERVER_CMD_REPLY_FUNC(identify)
796 {
797   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
798   SilcStatus status, error;
799
800   COMMAND_CHECK_STATUS;
801
802   if (!silc_server_command_reply_identify_save(cmd))
803     goto out;
804
805   /* Pending callbacks are not executed if this was an list entry */
806   if (status != SILC_STATUS_OK &&
807       status != SILC_STATUS_LIST_END) {
808     silc_server_command_reply_free(cmd);
809     return;
810   }
811
812  out:
813   silc_server_command_process_error(cmd, error);
814   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
815   silc_server_command_reply_free(cmd);
816   return;
817
818  err:
819   silc_server_command_process_error(cmd, error);
820   silc_server_command_reply_free(cmd);
821 }
822
823 /* Received reply fro INFO command. Cache the server and its information */
824
825 SILC_SERVER_CMD_REPLY_FUNC(info)
826 {
827   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
828   SilcServer server = cmd->server;
829   SilcStatus status, error;
830   SilcServerEntry entry;
831   SilcID id;
832   SilcUInt32 tmp_len;
833   unsigned char *tmp, *name;
834
835   COMMAND_CHECK_STATUS;
836
837   /* Get Server ID */
838   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
839     goto out;
840
841   /* Get the name */
842   name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
843   if (!name)
844     goto out;
845
846   entry = silc_idlist_find_server_by_id(server->local_list,
847                                         SILC_ID_GET_ID(id),
848                                         FALSE, NULL);
849   if (!entry) {
850     entry = silc_idlist_find_server_by_id(server->global_list,
851                                           SILC_ID_GET_ID(id),
852                                           FALSE, NULL);
853     if (!entry) {
854       /* Add the server to global list */
855       entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
856                                      silc_id_dup(SILC_ID_GET_ID(id),
857                                                  SILC_ID_SERVER),
858                                      silc_packet_get_context(cmd->sock),
859                                      cmd->sock);
860       if (!entry)
861         goto out;
862
863       entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
864     }
865   }
866
867   /* Get the info string */
868   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
869   if (tmp_len > 256)
870     tmp = NULL;
871
872   entry->server_info = tmp ? strdup(tmp) : NULL;
873
874  out:
875   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
876  err:
877   silc_server_command_reply_free(cmd);
878 }
879
880 /* Received reply fro MOTD command. */
881
882 SILC_SERVER_CMD_REPLY_FUNC(motd)
883 {
884   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
885   SilcServer server = cmd->server;
886   SilcStatus status, error;
887   SilcServerEntry entry = NULL;
888   SilcID id;
889   SilcUInt32 tmp_len;
890   unsigned char *tmp;
891
892   COMMAND_CHECK_STATUS;
893
894   /* Get Server ID */
895   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
896     goto out;
897
898   entry = silc_idlist_find_server_by_id(server->local_list,
899                                         SILC_ID_GET_ID(id),
900                                         TRUE, NULL);
901   if (!entry) {
902     entry = silc_idlist_find_server_by_id(server->global_list,
903                                           SILC_ID_GET_ID(id),
904                                           TRUE, NULL);
905     if (!entry) {
906       SilcBuffer buffer;
907
908       /* If router did not find such Server ID in its lists then this must
909          be bogus client or some router in the net is buggy. */
910       if (server->server_type != SILC_SERVER)
911         goto out;
912
913       /* Statistics */
914       cmd->server->stat.commands_sent++;
915
916       /* entry isn't known so we IDENTIFY it. otherwise the
917          silc_server_command_motd won't know about it and tell
918          the client that there is no such server */
919       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
920       buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
921                                               ++server->cmd_ident, 5,
922                                               1, NULL, 0, 2, NULL, 0,
923                                               3, NULL, 0, 4, NULL, 0,
924                                               5, tmp, tmp_len);
925       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
926                               SILC_PACKET_COMMAND, 0, buffer->data,
927                               silc_buffer_len(buffer));
928       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
929                                   server->cmd_ident,
930                                   silc_server_command_reply_motd,
931                                   cmd);
932       silc_buffer_free(buffer);
933       return;
934     }
935   }
936
937   /* Get the motd */
938   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
939   if (tmp_len > 256)
940     tmp = NULL;
941
942   entry->motd = tmp;
943
944  out:
945   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
946  err:
947   silc_server_command_reply_free(cmd);
948
949   if (entry)
950     entry->motd = NULL;
951 }
952
953 /* Received reply for forwarded JOIN command. Router has created or joined
954    the client to the channel. We save some channel information locally
955    for future use. */
956
957 SILC_SERVER_CMD_REPLY_FUNC(join)
958 {
959   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
960   SilcServer server = cmd->server;
961   SilcIDCacheEntry cache = NULL;
962   SilcStatus status, error;
963   SilcID id, id2;
964   SilcChannelEntry entry;
965   SilcHmac hmac = NULL;
966   SilcUInt32 len, list_count;
967   char *channel_name, *channel_namec = NULL, *tmp;
968   SilcUInt32 mode, created;
969   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
970   SilcPublicKey founder_key = NULL;
971
972   COMMAND_CHECK_STATUS;
973
974   /* Get channel name */
975   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
976   if (!channel_name)
977     goto out;
978
979   /* Get channel ID */
980   if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
981     goto out;
982
983   /* Get client ID */
984   if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
985     goto out;
986
987   /* Get mode mask */
988   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
989   if (!tmp)
990     goto out;
991   SILC_GET32_MSB(mode, tmp);
992
993   /* Get created boolean value */
994   tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
995   if (!tmp)
996     goto out;
997   SILC_GET32_MSB(created, tmp);
998   if (created != 0 && created != 1)
999     goto out;
1000
1001   /* Get channel key */
1002   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1003   if (tmp) {
1004     keyp = silc_buffer_alloc(len);
1005     silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1006     silc_buffer_put(keyp, tmp, len);
1007   }
1008
1009   /* Get hmac */
1010   tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1011   if (tmp) {
1012     if (!silc_hmac_alloc(tmp, NULL, &hmac))
1013       goto out;
1014   }
1015
1016   /* Get the list count */
1017   tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1018   if (!tmp)
1019     goto out;
1020   SILC_GET32_MSB(list_count, tmp);
1021
1022   /* Get Client ID list */
1023   tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1024   if (!tmp)
1025     goto out;
1026
1027   client_id_list = silc_buffer_alloc(len);
1028   silc_buffer_pull_tail(client_id_list, len);
1029   silc_buffer_put(client_id_list, tmp, len);
1030
1031   /* Get client mode list */
1032   tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1033   if (!tmp)
1034     goto out;
1035
1036   client_mode_list = silc_buffer_alloc(len);
1037   silc_buffer_pull_tail(client_mode_list, len);
1038   silc_buffer_put(client_mode_list, tmp, len);
1039
1040   /* Get founder key */
1041   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1042   if (tmp)
1043     silc_public_key_payload_decode(tmp, len, &founder_key);
1044
1045   /* See whether we already have the channel. */
1046   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1047                                           SILC_STRING_UTF8, 256, NULL);
1048   if (!channel_namec)
1049     goto out;
1050   entry = silc_idlist_find_channel_by_name(server->local_list,
1051                                            channel_namec, &cache);
1052   if (!entry) {
1053     /* Add new channel */
1054
1055     SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1056                     (created == 0 ? "existing" : "created"), channel_name,
1057                     silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1058
1059     /* If the channel is found from global list we must move it to the
1060        local list. */
1061     entry = silc_idlist_find_channel_by_name(server->global_list,
1062                                              channel_namec, &cache);
1063     if (entry)
1064       silc_idlist_del_channel(server->global_list, entry);
1065
1066     /* Add the channel to our local list. */
1067     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1068                                     SILC_CHANNEL_MODE_NONE,
1069                                     silc_id_dup(SILC_ID_GET_ID(id),
1070                                                 SILC_ID_CHANNEL),
1071                                     server->router, NULL, NULL, hmac);
1072     if (!entry)
1073       goto out;
1074
1075     hmac = NULL;
1076     server->stat.my_channels++;
1077     server->stat.channels++;
1078   } else {
1079     /* The entry exists. */
1080
1081     /* If ID has changed, then update it to the cache too. */
1082     if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1083       silc_idlist_replace_channel_id(server->local_list, entry->id,
1084                                      SILC_ID_GET_ID(id));
1085
1086     entry->disabled = FALSE;
1087
1088     /* Remove the founder auth data if the mode is not set but we have
1089        them in the entry */
1090     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1091       silc_pkcs_public_key_free(entry->founder_key);
1092       entry->founder_key = NULL;
1093     }
1094   }
1095
1096   if (founder_key) {
1097     if (entry->founder_key)
1098       silc_pkcs_public_key_free(entry->founder_key);
1099     entry->founder_key = founder_key;
1100     founder_key = NULL;
1101   }
1102
1103   if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1104     silc_free(entry->hmac_name);
1105     entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1106   }
1107
1108   /* Get the ban list */
1109   tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1110   if (tmp && len > 2) {
1111     SilcArgumentPayload iargs;
1112     SilcUInt16 iargc;
1113     SILC_GET16_MSB(iargc, tmp);
1114     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1115     if (iargs) {
1116       /* Delete old ban list */
1117       if (entry->ban_list)
1118         silc_hash_table_free(entry->ban_list);
1119       entry->ban_list =
1120         silc_hash_table_alloc(0, silc_hash_ptr,
1121                               NULL, NULL, NULL,
1122                               silc_server_inviteban_destruct, entry, TRUE);
1123
1124       /* Add new ban list */
1125       silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1126       silc_argument_payload_free(iargs);
1127     }
1128   }
1129
1130   /* Get the invite list */
1131   tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1132   if (tmp && len > 2) {
1133     SilcArgumentPayload iargs;
1134     SilcUInt16 iargc;
1135     SILC_GET16_MSB(iargc, tmp);
1136     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1137     if (iargs) {
1138       /* Delete old invite list */
1139       if (entry->invite_list)
1140         silc_hash_table_free(entry->invite_list);
1141       entry->invite_list =
1142         silc_hash_table_alloc(0, silc_hash_ptr,
1143                               NULL, NULL, NULL,
1144                               silc_server_inviteban_destruct, entry, TRUE);
1145
1146       /* Add new invite list */
1147       silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1148       silc_argument_payload_free(iargs);
1149     }
1150   }
1151
1152   /* Get the topic */
1153   tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1154   if (tmp) {
1155     silc_free(entry->topic);
1156     entry->topic = strdup(tmp);
1157   }
1158
1159   /* Get channel public key list */
1160   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1161   if (tmp && server->server_type != SILC_ROUTER)
1162     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1163
1164   /* The the user limit */
1165   tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1166   if (tmp && len == 4)
1167     SILC_GET32_MSB(entry->user_limit, tmp);
1168
1169   /* If channel was not created we know there is global users on the
1170      channel. */
1171   entry->global_users = (created == 0 ? TRUE : FALSE);
1172
1173   /* If channel was just created the mask must be zero */
1174   if (!entry->global_users && mode)
1175     mode = 0;
1176
1177   /* Save channel mode */
1178   entry->mode = mode;
1179
1180   /* Save channel key */
1181   if (keyp) {
1182     if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1183       silc_server_save_channel_key(server, keyp, entry);
1184     silc_buffer_free(keyp);
1185   }
1186
1187   /* Save the users to the channel */
1188   silc_server_save_users_on_channel(server, cmd->sock, entry,
1189                                     SILC_ID_GET_ID(id2), client_id_list,
1190                                     client_mode_list, list_count);
1191   entry->users_resolved = TRUE;
1192
1193  out:
1194   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1195  err:
1196   silc_free(channel_namec);
1197   if (hmac)
1198     silc_hmac_free(hmac);
1199   silc_server_command_reply_free(cmd);
1200
1201   if (founder_key)
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 }