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