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