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