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