updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      uint32 arg_type,
38                                      const unsigned char *arg,
39                                      uint32 arg_len);
40 static bool
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42                                         SilcServerCommandReplyContext cmdr,
43                                         SilcCommand command);
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
45
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
48 {
49   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59   SILC_SERVER_CMD(connect, CONNECT, 
60                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(close, CLOSE,
71                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
73                   SILC_CF_OPER),
74   SILC_SERVER_CMD(silcoper, SILCOPER,
75                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79
80   { NULL, 0 },
81 };
82
83 /* Performs several checks to the command. It first checks whether this
84    command was called as pending command callback. If it was then it checks
85    whether error occurred in the command reply where the pending command
86    callback was called. 
87
88    It also checks that the requested command includes correct amount
89    of arguments. */
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                 \
91 do {                                                                          \
92   uint32 _argc;                                                               \
93                                                                               \
94   SILC_LOG_DEBUG(("Start"));                                                  \
95                                                                               \
96   if (silc_server_command_pending_error_check(cmd, context2, command)) {      \
97     silc_server_command_free(cmd);                                            \
98     return;                                                                   \
99   }                                                                           \
100                                                                               \
101   _argc = silc_argument_get_arg_num(cmd->args);                               \
102   if (_argc < min) {                                                          \
103     silc_server_command_send_status_reply(cmd, command,                       \
104                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105     silc_server_command_free(cmd);                                            \
106     return;                                                                   \
107   }                                                                           \
108   if (_argc > max) {                                                          \
109     silc_server_command_send_status_reply(cmd, command,                       \
110                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
111     silc_server_command_free(cmd);                                            \
112     return;                                                                   \
113   }                                                                           \
114 } while(0)
115
116 /* Returns TRUE if the connection is registered. Unregistered connections
117    usually cannot send commands hence the check. */
118
119 static int silc_server_is_registered(SilcServer server,
120                                      SilcSocketConnection sock,
121                                      SilcServerCommandContext cmd,
122                                      SilcCommand command)
123 {
124   SilcIDListData idata = (SilcIDListData)sock->user_data;
125
126   if (!idata)
127     return FALSE;
128
129   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
130     return TRUE;
131
132   silc_server_command_send_status_reply(cmd, command,
133                                         SILC_STATUS_ERR_NOT_REGISTERED);
134   return FALSE;
135 }
136
137 /* Internal context to hold data when executed command with timeout. */
138 typedef struct {
139   SilcServerCommandContext ctx;
140   SilcServerCommand *cmd;
141 } *SilcServerCommandTimeout;
142
143 /* Timeout callback to process commands with timeout for client. Client's
144    commands are always executed with timeout. */
145
146 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
147 {
148   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
149   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
150
151   if (!client) {
152     silc_server_command_free(timeout->ctx);
153     silc_free(timeout);
154   }
155
156   /* Update access time */
157   client->last_command = time(NULL);
158
159   if (!(timeout->cmd->flags & SILC_CF_REG))
160     timeout->cmd->cb(timeout->ctx, NULL);
161   else if (silc_server_is_registered(timeout->ctx->server, 
162                                      timeout->ctx->sock, 
163                                      timeout->ctx, 
164                                      timeout->cmd->cmd))
165     timeout->cmd->cb(timeout->ctx, NULL);
166   else
167     silc_server_command_free(timeout->ctx);
168
169   silc_free(timeout);
170 }
171
172 /* Processes received command packet. */
173
174 void silc_server_command_process(SilcServer server,
175                                  SilcSocketConnection sock,
176                                  SilcPacketContext *packet)
177 {
178   SilcServerCommandContext ctx;
179   SilcServerCommand *cmd;
180   SilcCommand command;
181
182   /* Allocate command context. This must be free'd by the
183      command routine receiving it. */
184   ctx = silc_server_command_alloc();
185   ctx->server = server;
186   ctx->sock = silc_socket_dup(sock);
187   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
188   
189   /* Parse the command payload in the packet */
190   ctx->payload = silc_command_payload_parse(packet->buffer->data,
191                                             packet->buffer->len);
192   if (!ctx->payload) {
193     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
194     silc_buffer_free(packet->buffer);
195     silc_packet_context_free(packet);
196     silc_socket_free(ctx->sock);
197     silc_free(ctx);
198     return;
199   }
200   ctx->args = silc_command_get_args(ctx->payload);
201
202   /* Get the command */
203   command = silc_command_get(ctx->payload);
204   for (cmd = silc_command_list; cmd->cb; cmd++)
205     if (cmd->cmd == command)
206       break;
207
208   if (cmd == NULL) {
209     silc_server_command_send_status_reply(ctx, command,
210                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
211     silc_server_command_free(ctx);
212     return;
213   }
214
215   /* Execute client's commands always with timeout.  Normally they are
216      executed with zero (0) timeout but if client is sending command more
217      frequently than once in 2 seconds, then the timeout may be 0 to 2
218      seconds. */
219   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
220     SilcClientEntry client = (SilcClientEntry)sock->user_data;
221     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
222     int fast;
223
224     timeout->ctx = ctx;
225     timeout->cmd = cmd;
226
227     if (client->last_command && (time(NULL) - client->last_command) < 2) {
228       client->fast_command++;
229       fast = FALSE;
230     } else {
231       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
232                               client->fast_command--);
233       fast = TRUE;
234     }
235
236     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
237                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
238       silc_schedule_task_add(server->schedule, sock->sock, 
239                          silc_server_command_process_timeout,
240                          (void *)timeout, 
241                          2 - (time(NULL) - client->last_command), 0,
242                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
243     else
244       silc_schedule_task_add(server->schedule, sock->sock, 
245                          silc_server_command_process_timeout,
246                          (void *)timeout, 0, 1,
247                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
248     return;
249   }
250
251   /* Execute for server */
252
253   if (!(cmd->flags & SILC_CF_REG))
254     cmd->cb(ctx, NULL);
255   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256     cmd->cb(ctx, NULL);
257   else
258     silc_server_command_free(ctx);
259 }
260
261 /* Allocate Command Context */
262
263 SilcServerCommandContext silc_server_command_alloc()
264 {
265   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
266   ctx->users++;
267   return ctx;
268 }
269
270 /* Free's the command context allocated before executing the command */
271
272 void silc_server_command_free(SilcServerCommandContext ctx)
273 {
274   ctx->users--;
275   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
276                   ctx->users));
277   if (ctx->users < 1) {
278     if (ctx->payload)
279       silc_command_payload_free(ctx->payload);
280     if (ctx->packet)
281       silc_packet_context_free(ctx->packet);
282     if (ctx->sock)
283       silc_socket_free(ctx->sock); /* Decrease reference counter */
284     silc_free(ctx);
285   }
286 }
287
288 /* Duplicate Command Context by adding reference counter. The context won't
289    be free'd untill it hits zero. */
290
291 SilcServerCommandContext 
292 silc_server_command_dup(SilcServerCommandContext ctx)
293 {
294   ctx->users++;
295   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
296                   ctx->users));
297   return ctx;
298 }
299
300 /* Add new pending command to be executed when reply to a command has been
301    received. The `reply_cmd' is the command that will call the `callback'
302    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
303    to match any command with the `ident'.  If `ident' is non-zero
304    the `callback' will be executed when received reply with command
305    identifier `ident'. If there already exists pending command for the
306    specified command, ident, callback and context this function has no
307    effect. */
308
309 bool silc_server_command_pending(SilcServer server,
310                                  SilcCommand reply_cmd,
311                                  uint16 ident,
312                                  SilcCommandCb callback,
313                                  void *context)
314 {
315   SilcServerCommandPending *reply;
316
317   /* Check whether identical pending already exists for same command,
318      ident, callback and callback context. If it does then it would be
319      error to register it again. */
320   silc_dlist_start(server->pending_commands);
321   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
322     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
323         reply->callback == callback && reply->context == context)
324       return FALSE;
325   }
326
327   reply = silc_calloc(1, sizeof(*reply));
328   reply->reply_cmd = reply_cmd;
329   reply->ident = ident;
330   reply->context = context;
331   reply->callback = callback;
332   silc_dlist_add(server->pending_commands, reply);
333
334   return TRUE;
335 }
336
337 /* Deletes pending command by reply command type. */
338
339 void silc_server_command_pending_del(SilcServer server,
340                                      SilcCommand reply_cmd,
341                                      uint16 ident)
342 {
343   SilcServerCommandPending *r;
344
345   silc_dlist_start(server->pending_commands);
346   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
347     if (r->reply_cmd == reply_cmd && r->ident == ident) {
348       silc_dlist_del(server->pending_commands, r);
349       break;
350     }
351   }
352 }
353
354 /* Checks for pending commands and marks callbacks to be called from
355    the command reply function. Returns TRUE if there were pending command. */
356
357 SilcServerCommandPendingCallbacks
358 silc_server_command_pending_check(SilcServer server,
359                                   SilcServerCommandReplyContext ctx,
360                                   SilcCommand command, 
361                                   uint16 ident,
362                                   uint32 *callbacks_count)
363 {
364   SilcServerCommandPending *r;
365   SilcServerCommandPendingCallbacks callbacks = NULL;
366   int i = 0;
367
368   silc_dlist_start(server->pending_commands);
369   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
370     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
371         && r->ident == ident) {
372       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
373       callbacks[i].context = r->context;
374       callbacks[i].callback = r->callback;
375       ctx->ident = ident;
376       i++;
377     }
378   }
379
380   *callbacks_count = i;
381   return callbacks;
382 }
383
384 /* Sends simple status message as command reply packet */
385
386 static void 
387 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
388                                       SilcCommand command,
389                                       SilcCommandStatus status)
390 {
391   SilcBuffer buffer;
392
393   SILC_LOG_DEBUG(("Sending command status %d", status));
394
395   buffer = 
396     silc_command_reply_payload_encode_va(command, status, 
397                                          silc_command_get_ident(cmd->payload),
398                                          0);
399   silc_server_packet_send(cmd->server, cmd->sock,
400                           SILC_PACKET_COMMAND_REPLY, 0, 
401                           buffer->data, buffer->len, FALSE);
402   silc_buffer_free(buffer);
403 }
404
405 /* Sends command status reply with one extra argument. The argument
406    type must be sent as argument. */
407
408 static void 
409 silc_server_command_send_status_data(SilcServerCommandContext cmd,
410                                      SilcCommand command,
411                                      SilcCommandStatus status,
412                                      uint32 arg_type,
413                                      const unsigned char *arg,
414                                      uint32 arg_len)
415 {
416   SilcBuffer buffer;
417
418   SILC_LOG_DEBUG(("Sending command status %d", status));
419
420   buffer = 
421     silc_command_reply_payload_encode_va(command, status, 
422                                          silc_command_get_ident(cmd->payload),
423                                          1, arg_type, arg, arg_len);
424   silc_server_packet_send(cmd->server, cmd->sock,
425                           SILC_PACKET_COMMAND_REPLY, 0, 
426                           buffer->data, buffer->len, FALSE);
427   silc_buffer_free(buffer);
428 }
429
430 /* This function can be called to check whether in the command reply
431    an error occurred. This function has no effect if this is called
432    when the command function was not called as pending command callback. 
433    This returns TRUE if error had occurred. */
434
435 static bool
436 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
437                                         SilcServerCommandReplyContext cmdr,
438                                         SilcCommand command)
439 {
440   SilcCommandStatus status;
441
442   if (!cmd->pending || !cmdr)
443     return FALSE;
444
445   SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
446   if (status != SILC_STATUS_OK &&
447       status != SILC_STATUS_LIST_START &&
448       status != SILC_STATUS_LIST_ITEM &&
449       status != SILC_STATUS_LIST_END) {
450     SilcBuffer buffer;
451
452     /* Send the same command reply payload */
453     silc_command_set_ident(cmdr->payload, 
454                            silc_command_get_ident(cmd->payload));
455     buffer = silc_command_payload_encode_payload(cmdr->payload);
456     silc_server_packet_send(cmd->server, cmd->sock,
457                             SILC_PACKET_COMMAND_REPLY, 0, 
458                             buffer->data, buffer->len, FALSE);
459     silc_buffer_free(buffer);
460     return TRUE;
461   }
462
463   return FALSE;
464 }
465
466 /******************************************************************************
467
468                               WHOIS Functions
469
470 ******************************************************************************/
471
472 static int
473 silc_server_command_whois_parse(SilcServerCommandContext cmd,
474                                 SilcClientID ***client_id,
475                                 uint32 *client_id_count,
476                                 char **nickname,
477                                 char **server_name,
478                                 int *count,
479                                 SilcCommand command)
480 {
481   unsigned char *tmp;
482   uint32 len;
483   uint32 argc = silc_argument_get_arg_num(cmd->args);
484   int i, k;
485
486   /* If client ID is in the command it must be used instead of nickname */
487   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
488   if (!tmp) {
489     /* No ID, get the nickname@server string and parse it. */
490     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
491     if (tmp) {
492       silc_parse_userfqdn(tmp, nickname, server_name);
493     } else {
494       silc_server_command_send_status_reply(cmd, command,
495                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
496       return FALSE;
497     }
498   } else {
499     /* Command includes ID, we must use that.  Also check whether the command
500        has more than one ID set - take them all. */
501
502     *client_id = silc_calloc(1, sizeof(**client_id));
503     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
504     if ((*client_id)[0] == NULL) {
505       silc_free(*client_id);
506       silc_server_command_send_status_reply(cmd, command,
507                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
508       return FALSE;
509     }
510     *client_id_count = 1;
511
512     /* Take all ID's from the command packet */
513     if (argc > 1) {
514       for (k = 1, i = 1; i < argc; i++) {
515         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
516         if (tmp) {
517           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
518                                     (*client_id_count + 1));
519           (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
520           if ((*client_id)[k] == NULL) {
521             /* Cleanup all and fail */
522             for (i = 0; i < *client_id_count; i++)
523               silc_free((*client_id)[i]);
524             silc_free(*client_id);
525             silc_server_command_send_status_reply(
526                                          cmd, command,
527                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
528             return FALSE;
529           }
530           (*client_id_count)++;
531           k++;
532         }
533       }
534     }
535   }
536
537   /* Get the max count of reply messages allowed */
538   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
539   if (tmp)
540     *count = atoi(tmp);
541   else
542     *count = 0;
543
544   return TRUE;
545 }
546
547 /* Resolve context used by both WHOIS and IDENTIFY commands */
548 typedef struct {
549   SilcServerEntry router;
550   uint16 ident;
551   unsigned char **res_argv;
552   uint32 *res_argv_lens;
553   uint32 *res_argv_types;
554   uint32 res_argc;
555 } *SilcServerResolveContext;
556
557 static bool
558 silc_server_command_whois_check(SilcServerCommandContext cmd,
559                                 SilcClientEntry *clients,
560                                 uint32 clients_count)
561 {
562   SilcServer server = cmd->server;
563   SilcClientEntry entry;
564   SilcServerResolveContext resolve = NULL, r = NULL;
565   uint32 resolve_count = 0;
566   int i, k;
567   bool no_res = TRUE;
568
569   SILC_LOG_DEBUG(("Start"));
570
571   for (i = 0; i < clients_count; i++) {
572     entry = clients[i];
573     if (!entry)
574       continue;
575
576     if ((entry->nickname && entry->username && entry->userinfo) ||
577         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
578       if (!entry->router)
579         continue;
580
581       /* If we are normal server, and we've not resolved this client from
582          router and it is global client, we'll check whether it is on some
583          channel.  If not then we cannot be sure about its validity, and
584          we'll resolve it from router. */
585       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
586           entry->connection || silc_hash_table_count(entry->channels))
587         continue;
588     }
589
590     /* We need to resolve this entry since it is not complete */
591
592     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
593       /* The entry is being resolved (and we are not the resolver) so attach
594          to the command reply and we're done with this one. */
595       silc_server_command_pending(server, SILC_COMMAND_NONE, 
596                                   entry->resolve_cmd_ident,
597                                   silc_server_command_whois,
598                                   silc_server_command_dup(cmd));
599       no_res = FALSE;
600     } else {
601       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
602         /* We've resolved this and it still is not ready.  We'll return
603            and are that this will be handled again after it is resolved. */
604         for (i = 0; i < resolve_count; i++) {
605           for (k = 0; k < r->res_argc; k++)
606             silc_free(r->res_argv[k]);
607           silc_free(r->res_argv);
608           silc_free(r->res_argv_lens);
609           silc_free(r->res_argv_types);
610         }
611         silc_free(resolve);
612         return FALSE;
613       } else {
614         /* We'll resolve this client */
615         SilcBuffer idp;
616
617         r = NULL;
618         for (k = 0; k < resolve_count; k++) {
619           if (resolve[k].router == entry->router) {
620             r = &resolve[k];
621             break;
622           }
623         }
624
625         if (!r) {
626           resolve = silc_realloc(resolve, sizeof(*resolve) * 
627                                  (resolve_count + 1));
628           r = &resolve[resolve_count];
629           memset(r, 0, sizeof(*r));
630           r->router = entry->router;
631           r->ident = ++server->cmd_ident;
632           resolve_count++;
633         }
634
635         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
636                                    (r->res_argc + 1));
637         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
638                                         sizeof(*r->res_argv_lens) *
639                                         (r->res_argc + 1));
640         r->res_argv_types = silc_realloc(r->res_argv_types, 
641                                          sizeof(*r->res_argv_types) *
642                                          (r->res_argc + 1));
643         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
644         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
645                                                sizeof(**r->res_argv));
646         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
647         r->res_argv_lens[r->res_argc] = idp->len;
648         r->res_argv_types[r->res_argc] = r->res_argc + 3;
649         r->res_argc++;
650         silc_buffer_free(idp);
651
652         entry->resolve_cmd_ident = r->ident;
653         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
654         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
655       }
656     }
657   }
658
659   /* Do the resolving */
660   for (i = 0; i < resolve_count; i++) {
661     SilcBuffer res_cmd;
662
663     r = &resolve[i];
664
665     /* Send WHOIS request. We send WHOIS since we're doing the requesting
666        now anyway so make it a good one. */
667     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
668                                           r->res_argc, r->res_argv, 
669                                           r->res_argv_lens,
670                                           r->res_argv_types, 
671                                           r->ident);
672     silc_server_packet_send(server, r->router->connection,
673                             SILC_PACKET_COMMAND, cmd->packet->flags,
674                             res_cmd->data, res_cmd->len, FALSE);
675
676     /* Reprocess this packet after received reply */
677     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
678                                 r->ident,
679                                 silc_server_command_whois,
680                                 silc_server_command_dup(cmd));
681     cmd->pending = TRUE;
682
683     silc_buffer_free(res_cmd);
684     for (k = 0; k < r->res_argc; k++)
685       silc_free(r->res_argv[k]);
686     silc_free(r->res_argv);
687     silc_free(r->res_argv_lens);
688     silc_free(r->res_argv_types);
689     no_res = FALSE;
690   }
691   silc_free(resolve);
692
693   return no_res;
694 }
695
696 static void
697 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
698                                      SilcClientEntry *clients,
699                                      uint32 clients_count,
700                                      int count,
701                                      const char *nickname,
702                                      SilcClientID **client_ids)
703 {
704   SilcServer server = cmd->server;
705   char *tmp;
706   int i, k, len, valid_count;
707   SilcBuffer packet, idp, channels;
708   SilcClientEntry entry;
709   SilcCommandStatus status;
710   uint16 ident = silc_command_get_ident(cmd->payload);
711   char nh[256], uh[256];
712   unsigned char idle[4], mode[4];
713   unsigned char *fingerprint;
714   SilcSocketConnection hsock;
715
716   /* Process only valid clients and ignore those that are not registered. */
717   valid_count = 0;
718   for (i = 0; i < clients_count; i++) {
719     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
720       valid_count++;
721     else
722       clients[i] = NULL;
723   }
724
725   if (!valid_count) {
726     /* No valid clients found, send error reply */
727     if (nickname) {
728       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
729                                            SILC_STATUS_ERR_NO_SUCH_NICK,
730                                            3, nickname, strlen(nickname));
731     } else if (client_ids && client_ids[0]) {
732       SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
733       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
734                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
735                                            2, idp->data, idp->len);
736       silc_buffer_free(idp);
737     }
738     return;
739   }
740
741   /* Start processing found clients. */
742   if (valid_count > 1)
743     status = SILC_STATUS_LIST_START;
744   else
745     status = SILC_STATUS_OK;
746
747   for (i = 0, k = 0; i < clients_count; i++) {
748     entry = clients[i];
749     if (!entry)
750       continue;
751
752     if (k >= 1)
753       status = SILC_STATUS_LIST_ITEM;
754     if (valid_count > 1 && k == valid_count - 1)
755       status = SILC_STATUS_LIST_END;
756     if (count && k - 1 == count)
757       status = SILC_STATUS_LIST_END;
758
759     /* Send WHOIS reply */
760     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
761     tmp = silc_argument_get_first_arg(cmd->args, NULL);
762     
763     memset(uh, 0, sizeof(uh));
764     memset(nh, 0, sizeof(nh));
765     memset(idle, 0, sizeof(idle));
766     
767     strncat(nh, entry->nickname, strlen(entry->nickname));
768     if (!strchr(entry->nickname, '@')) {
769       strncat(nh, "@", 1);
770       if (entry->servername) {
771         strncat(nh, entry->servername, strlen(entry->servername));
772       } else {
773         len = entry->router ? strlen(entry->router->server_name) :
774           strlen(server->server_name);
775         strncat(nh, entry->router ? entry->router->server_name :
776                 server->server_name, len);
777       }
778     }
779       
780     strncat(uh, entry->username, strlen(entry->username));
781     if (!strchr(entry->username, '@')) {
782       strncat(uh, "@", 1);
783       hsock = (SilcSocketConnection)entry->connection;
784       len = strlen(hsock->hostname);
785       strncat(uh, hsock->hostname, len);
786     }
787
788     channels = silc_server_get_client_channel_list(server, entry);
789
790     if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
791       fingerprint = entry->data.fingerprint;
792     else
793       fingerprint = NULL;
794       
795     SILC_PUT32_MSB(entry->mode, mode);
796
797     if (entry->connection) {
798       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
799     }
800
801     packet = 
802       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
803                                            status, ident, 8, 
804                                            2, idp->data, idp->len,
805                                            3, nh, strlen(nh),
806                                            4, uh, strlen(uh),
807                                            5, entry->userinfo, 
808                                            strlen(entry->userinfo),
809                                            6, channels ? channels->data : NULL,
810                                            channels ? channels->len : 0,
811                                            7, mode, 4,
812                                            8, idle, 4,
813                                            9, fingerprint,
814                                            fingerprint ? 20 : 0);
815
816     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
817                             0, packet->data, packet->len, FALSE);
818     
819     silc_buffer_free(packet);
820     silc_buffer_free(idp);
821     if (channels)
822       silc_buffer_free(channels);
823
824     k++;
825   }
826 }
827
828 static void 
829 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
830 {
831   SilcServer server = cmd->server;
832   SilcBuffer tmpbuf;
833   uint16 old_ident;
834
835   old_ident = silc_command_get_ident(cmd->payload);
836   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
837   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
838
839   /* Send WHOIS command to our router */
840   silc_server_packet_send(server, (SilcSocketConnection)
841                           server->router->connection,
842                           SILC_PACKET_COMMAND, cmd->packet->flags,
843                           tmpbuf->data, tmpbuf->len, TRUE);
844
845   /* Reprocess this packet after received reply from router */
846   silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
847                               silc_command_get_ident(cmd->payload),
848                               silc_server_command_whois,
849                               silc_server_command_dup(cmd));
850   cmd->pending = TRUE;
851   silc_command_set_ident(cmd->payload, old_ident);
852   silc_buffer_free(tmpbuf);
853 }
854
855 static int
856 silc_server_command_whois_process(SilcServerCommandContext cmd)
857 {
858   SilcServer server = cmd->server;
859   char *nick = NULL, *server_name = NULL;
860   int count = 0;
861   SilcClientEntry *clients = NULL, entry;
862   SilcClientID **client_id = NULL;
863   uint32 client_id_count = 0, clients_count = 0;
864   int i, ret = 0;
865   bool check_global = FALSE;
866
867   /* Parse the whois request */
868   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
869                                        &nick, &server_name, &count,
870                                        SILC_COMMAND_WHOIS))
871     return 0;
872
873   /* Send the WHOIS request to the router only if it included nickname.
874      Since nicknames can be expanded into many clients we need to send it
875      to router.  If the WHOIS included only client ID's we will check them
876      first locally since we just might have them. */
877   if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
878       server->server_type == SILC_SERVER && !cmd->pending &&
879       !server->standalone) {
880     silc_server_command_whois_send_router(cmd);
881     ret = -1;
882     goto out;
883   }
884
885   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
886     check_global = TRUE;
887   else if (server->server_type != SILC_SERVER)
888     check_global = TRUE;
889
890   /* Get all clients matching that ID or nickname from local list */
891   if (client_id_count) {
892     /* Check all Client ID's received in the command packet */
893     for (i = 0; i < client_id_count; i++) {
894       entry = silc_idlist_find_client_by_id(server->local_list, 
895                                             client_id[i], TRUE, NULL);
896       if (!entry && check_global)
897         entry = silc_idlist_find_client_by_id(server->global_list, 
898                                               client_id[i], TRUE, NULL);
899       if (entry) {
900         clients = silc_realloc(clients, sizeof(*clients) * 
901                                (clients_count + 1));
902         clients[clients_count++] = entry;
903       } else {
904         /* If we are normal server and did not send the request first to router
905            do it now, since we do not have the Client ID information. */
906         if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
907             server->server_type == SILC_SERVER && !cmd->pending && 
908             !server->standalone) {
909           silc_server_command_whois_send_router(cmd);
910           ret = -1;
911           goto out;
912         }
913       }
914     }
915   } else {
916     /* Find by nickname */
917     if (!silc_idlist_get_clients_by_hash(server->local_list, 
918                                          nick, server->md5hash,
919                                          &clients, &clients_count))
920       silc_idlist_get_clients_by_nickname(server->local_list, 
921                                           nick, server_name,
922                                           &clients, &clients_count);
923     if (check_global) {
924       if (!silc_idlist_get_clients_by_hash(server->global_list, 
925                                            nick, server->md5hash,
926                                            &clients, &clients_count))
927         silc_idlist_get_clients_by_nickname(server->global_list, 
928                                             nick, server_name,
929                                             &clients, &clients_count);
930     }
931   }
932   
933   if (!clients) {
934     /* If we are normal server and did not send the request first to router
935        do it now, since we do not have the information. */
936     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
937         server->server_type == SILC_SERVER && !cmd->pending && 
938         !server->standalone) {
939       silc_server_command_whois_send_router(cmd);
940       ret = -1;
941       goto out;
942     }
943
944     /* Such client(s) really does not exist in the SILC network. */
945     if (!client_id_count) {
946       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
947                                            SILC_STATUS_ERR_NO_SUCH_NICK,
948                                            3, nick, strlen(nick));
949     } else {
950       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
951       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
952                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
953                                            2, idp->data, idp->len);
954       silc_buffer_free(idp);
955     }
956     goto out;
957   }
958
959   /* Router always finds the client entry if it exists in the SILC network.
960      However, it might be incomplete entry and does not include all the
961      mandatory fields that WHOIS command reply requires. Check for these and
962      make query from the server who owns the client if some fields are 
963      missing. */
964   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
965     ret = -1;
966     goto out;
967   }
968
969   /* Send the command reply */
970   silc_server_command_whois_send_reply(cmd, clients, clients_count,
971                                        count, nick, client_id);
972
973  out:
974   if (client_id_count) {
975     for (i = 0; i < client_id_count; i++)
976       silc_free(client_id[i]);
977     silc_free(client_id);
978   }
979   silc_free(clients);
980   silc_free(nick);
981   silc_free(server_name);
982
983   return ret;
984 }
985
986 /* Server side of command WHOIS. Processes user's query and sends found 
987    results as command replies back to the client. */
988
989 SILC_SERVER_CMD_FUNC(whois)
990 {
991   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
992   int ret = 0;
993
994   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
995
996   ret = silc_server_command_whois_process(cmd);
997   silc_server_command_free(cmd);
998 }
999
1000 /******************************************************************************
1001
1002                               WHOWAS Functions
1003
1004 ******************************************************************************/
1005
1006 static int
1007 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1008                                  char **nickname,
1009                                  char **server_name,
1010                                  int *count)
1011 {
1012   unsigned char *tmp;
1013   uint32 len;
1014
1015   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1016   if (!tmp) {
1017     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1018                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1019     return FALSE;
1020   }
1021
1022   /* Get the nickname@server string and parse it. */
1023   silc_parse_userfqdn(tmp, nickname, server_name);
1024
1025   /* Get the max count of reply messages allowed */
1026   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1027   if (tmp)
1028     *count = atoi(tmp);
1029   else
1030     *count = 0;
1031
1032   return TRUE;
1033 }
1034
1035 static char
1036 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1037                                  SilcClientEntry *clients,
1038                                  uint32 clients_count)
1039 {
1040   SilcServer server = cmd->server;
1041   int i;
1042   SilcClientEntry entry;
1043
1044   for (i = 0; i < clients_count; i++) {
1045     entry = clients[i];
1046
1047     if (!entry->nickname || !entry->username) {
1048       SilcBuffer tmpbuf;
1049       uint16 old_ident;
1050
1051       if (!entry->router)
1052         continue;
1053       
1054       old_ident = silc_command_get_ident(cmd->payload);
1055       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1056       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1057
1058       /* Send WHOWAS command */
1059       silc_server_packet_send(server, entry->router->connection,
1060                               SILC_PACKET_COMMAND, cmd->packet->flags,
1061                               tmpbuf->data, tmpbuf->len, TRUE);
1062       
1063       /* Reprocess this packet after received reply */
1064       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1065                                   silc_command_get_ident(cmd->payload),
1066                                   silc_server_command_whowas, 
1067                                   silc_server_command_dup(cmd));
1068       cmd->pending = TRUE;
1069       silc_command_set_ident(cmd->payload, old_ident);
1070
1071       silc_buffer_free(tmpbuf);
1072       return FALSE;
1073     }
1074   }
1075
1076   return TRUE;
1077 }
1078
1079 static void
1080 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1081                                       SilcClientEntry *clients,
1082                                       uint32 clients_count)
1083 {
1084   SilcServer server = cmd->server;
1085   char *tmp;
1086   int i, k, count = 0, len;
1087   SilcBuffer packet, idp;
1088   SilcClientEntry entry = NULL;
1089   SilcCommandStatus status;
1090   uint16 ident = silc_command_get_ident(cmd->payload);
1091   char nh[256], uh[256];
1092   int valid_count;
1093
1094   status = SILC_STATUS_OK;
1095
1096   /* Process only entries that are not registered anymore. */
1097   valid_count = 0;
1098   for (i = 0; i < clients_count; i++) {
1099     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1100       clients[i] = NULL;
1101     else
1102       valid_count++;
1103   }
1104
1105   if (!valid_count) {
1106     /* No valid entries found at all, just send error */
1107     unsigned char *tmp;
1108     
1109     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1110     if (tmp)
1111       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1112                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1113                                            3, tmp, strlen(tmp));
1114     return;
1115   }
1116
1117   if (valid_count > 1)
1118     status = SILC_STATUS_LIST_START;
1119
1120   for (i = 0, k = 0; i < clients_count; i++) {
1121     entry = clients[i];
1122     if (!entry)
1123       continue;
1124
1125     if (k >= 1)
1126       status = SILC_STATUS_LIST_ITEM;
1127     if (valid_count > 1 && k == valid_count - 1)
1128       status = SILC_STATUS_LIST_END;
1129     if (count && k - 1 == count)
1130       status = SILC_STATUS_LIST_END;
1131     if (count && k - 1 > count)
1132       break;
1133
1134     /* Send WHOWAS reply */
1135     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1136     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1137     memset(uh, 0, sizeof(uh));
1138     memset(nh, 0, sizeof(nh));
1139
1140     strncat(nh, entry->nickname, strlen(entry->nickname));
1141     if (!strchr(entry->nickname, '@')) {
1142       strncat(nh, "@", 1);
1143       if (entry->servername) {
1144         strncat(nh, entry->servername, strlen(entry->servername));
1145       } else {
1146         len = entry->router ? strlen(entry->router->server_name) :
1147           strlen(server->server_name);
1148         strncat(nh, entry->router ? entry->router->server_name :
1149                 server->server_name, len);
1150       }
1151     }
1152       
1153     strncat(uh, entry->username, strlen(entry->username));
1154     if (!strchr(entry->username, '@')) {
1155       strncat(uh, "@", 1);
1156       strcat(uh, "*private*");
1157     }
1158       
1159     packet = 
1160       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1161                                            status, ident, 4, 
1162                                            2, idp->data, idp->len,
1163                                            3, nh, strlen(nh),
1164                                            4, uh, strlen(uh),
1165                                            5, entry->userinfo, 
1166                                            entry->userinfo ? 
1167                                            strlen(entry->userinfo) : 0);
1168     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1169                             0, packet->data, packet->len, FALSE);
1170     
1171     silc_buffer_free(packet);
1172     silc_buffer_free(idp);
1173
1174     k++;
1175   }
1176 }
1177
1178 static int
1179 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1180 {
1181   SilcServer server = cmd->server;
1182   char *nick = NULL, *server_name = NULL;
1183   int count = 0;
1184   SilcClientEntry *clients = NULL;
1185   uint32 clients_count = 0;
1186   int ret = 0;
1187   bool check_global = FALSE;
1188
1189   /* Protocol dictates that we must always send the received WHOWAS request
1190      to our router if we are normal server, so let's do it now unless we
1191      are standalone. We will not send any replies to the client until we
1192      have received reply from the router. */
1193   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1194       server->server_type == SILC_SERVER && !cmd->pending && 
1195       !server->standalone) {
1196     SilcBuffer tmpbuf;
1197     uint16 old_ident;
1198
1199     old_ident = silc_command_get_ident(cmd->payload);
1200     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1201     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1202
1203     /* Send WHOWAS command to our router */
1204     silc_server_packet_send(server, (SilcSocketConnection)
1205                             server->router->connection,
1206                             SILC_PACKET_COMMAND, cmd->packet->flags,
1207                             tmpbuf->data, tmpbuf->len, TRUE);
1208
1209     /* Reprocess this packet after received reply from router */
1210     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1211                                 silc_command_get_ident(cmd->payload),
1212                                 silc_server_command_whowas,
1213                                 silc_server_command_dup(cmd));
1214     cmd->pending = TRUE;
1215     silc_command_set_ident(cmd->payload, old_ident);
1216
1217     silc_buffer_free(tmpbuf);
1218     ret = -1;
1219     goto out;
1220   }
1221
1222   /* We are ready to process the command request. Let's search for the
1223      requested client and send reply to the requesting client. */
1224
1225   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1226     check_global = TRUE;
1227   else if (server->server_type != SILC_SERVER)
1228     check_global = TRUE;
1229
1230   /* Parse the whowas request */
1231   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1232     return 0;
1233
1234   /* Get all clients matching that nickname from local list */
1235   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1236                                            nick, server_name,
1237                                            &clients, &clients_count))
1238     silc_idlist_get_clients_by_hash(server->local_list, 
1239                                     nick, server->md5hash,
1240                                     &clients, &clients_count);
1241   
1242   /* Check global list as well */
1243   if (check_global) {
1244     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1245                                              nick, server_name,
1246                                              &clients, &clients_count))
1247       silc_idlist_get_clients_by_hash(server->global_list, 
1248                                       nick, server->md5hash,
1249                                       &clients, &clients_count);
1250   }
1251   
1252   if (!clients) {
1253     /* Such a client really does not exist in the SILC network. */
1254     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1255                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1256                                          3, nick, strlen(nick));
1257     goto out;
1258   }
1259
1260   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1261     ret = -1;
1262     goto out;
1263   }
1264
1265   /* Send the command reply to the client */
1266   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1267
1268  out:
1269   silc_free(clients);
1270   silc_free(nick);
1271   silc_free(server_name);
1272   return ret;
1273 }
1274
1275 /* Server side of command WHOWAS. */
1276
1277 SILC_SERVER_CMD_FUNC(whowas)
1278 {
1279   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1280   int ret = 0;
1281
1282   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1283
1284   ret = silc_server_command_whowas_process(cmd);
1285   silc_server_command_free(cmd);
1286 }
1287
1288 /******************************************************************************
1289
1290                               IDENTIFY Functions
1291
1292 ******************************************************************************/
1293
1294 static void 
1295 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1296 {
1297   SilcServer server = cmd->server;
1298   SilcBuffer tmpbuf;
1299   uint16 old_ident;
1300
1301   old_ident = silc_command_get_ident(cmd->payload);
1302   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1303   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1304
1305   /* Send IDENTIFY command to our router */
1306   silc_server_packet_send(server, (SilcSocketConnection)
1307                           server->router->connection,
1308                           SILC_PACKET_COMMAND, cmd->packet->flags,
1309                           tmpbuf->data, tmpbuf->len, TRUE);
1310
1311   /* Reprocess this packet after received reply from router */
1312   silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1313                               silc_command_get_ident(cmd->payload),
1314                               silc_server_command_identify,
1315                               silc_server_command_dup(cmd));
1316   cmd->pending = TRUE;
1317   silc_command_set_ident(cmd->payload, old_ident);
1318   silc_buffer_free(tmpbuf);
1319 }
1320
1321 static int
1322 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1323                                    SilcClientEntry **clients,
1324                                    uint32 *clients_count,
1325                                    SilcServerEntry **servers,
1326                                    uint32 *servers_count,
1327                                    SilcChannelEntry **channels,
1328                                    uint32 *channels_count,
1329                                    uint32 *count)
1330 {
1331   SilcServer server = cmd->server;
1332   unsigned char *tmp;
1333   uint32 len;
1334   uint32 argc = silc_argument_get_arg_num(cmd->args);
1335   SilcIDPayload idp;
1336   bool check_global = FALSE;
1337   void *entry;
1338   int i;
1339   bool error = FALSE;
1340
1341   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1342     check_global = TRUE;
1343   else if (server->server_type != SILC_SERVER)
1344     check_global = TRUE;
1345
1346   /* If ID Payload is in the command it must be used instead of names */
1347   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1348   if (!tmp) {
1349     /* No ID, get the names. */
1350
1351     /* If we are normal server and have not resolved information from
1352        router yet, do so now. */
1353     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1354         server->server_type == SILC_SERVER && !cmd->pending && 
1355         !server->standalone) {
1356       silc_server_command_identify_send_router(cmd);
1357       return -1;
1358     }
1359
1360     /* Try to get nickname@server. */
1361     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1362     if (tmp) {
1363       char *nick = NULL;
1364       char *nick_server = NULL;
1365
1366       silc_parse_userfqdn(tmp, &nick, &nick_server);
1367
1368       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1369                                            nick, server->md5hash,
1370                                            clients, clients_count))
1371         silc_idlist_get_clients_by_nickname(server->local_list, 
1372                                             nick, nick_server,
1373                                             clients, clients_count);
1374       if (check_global) {
1375         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1376                                              nick, server->md5hash,
1377                                              clients, clients_count))
1378           silc_idlist_get_clients_by_nickname(server->global_list, 
1379                                               nick, nick_server,
1380                                               clients, clients_count);
1381       }
1382
1383       silc_free(nick);
1384       silc_free(nick_server);
1385
1386       if (!(*clients)) {
1387         /* the nickname does not exist, send error reply */
1388         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1389                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1390                                              3, tmp, strlen(tmp));
1391         return 0;
1392       }
1393     }
1394
1395     /* Try to get server name */
1396     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1397     if (tmp) {
1398       entry = silc_idlist_find_server_by_name(server->local_list,
1399                                               tmp, TRUE, NULL);
1400       if (!entry && check_global)
1401         entry = silc_idlist_find_server_by_name(server->global_list,
1402                                                 tmp, TRUE, NULL);
1403       if (entry) {
1404         *servers = silc_realloc(*servers, sizeof(**servers) * 
1405                                 (*servers_count + 1));
1406         (*servers)[(*servers_count)++] = entry;
1407       }
1408
1409       if (!(*servers)) {
1410         /* the server does not exist, send error reply */
1411         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1412                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1413                                              3, tmp, strlen(tmp));
1414         return 0;
1415       }
1416     }
1417
1418     /* Try to get channel name */
1419     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1420     if (tmp) {
1421       entry = silc_idlist_find_channel_by_name(server->local_list,
1422                                                tmp, NULL);
1423       if (!entry && check_global)
1424         entry = silc_idlist_find_channel_by_name(server->global_list,
1425                                                  tmp, NULL);
1426       if (entry) {
1427         *channels = silc_realloc(*channels, sizeof(**channels) * 
1428                                  (*channels_count + 1));
1429         (*channels)[(*channels_count)++] = entry;
1430       }
1431
1432       if (!(*channels)) {
1433         /* The channel does not exist, send error reply */
1434         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1435                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1436                                              3, tmp, strlen(tmp));
1437         return 0;
1438       }
1439     }
1440
1441     if (!(*clients) && !(*servers) && !(*channels)) {
1442       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1443                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1444       return 0;
1445     }
1446   } else {
1447     /* Command includes ID, we must use that.  Also check whether the command
1448        has more than one ID set - take them all. */
1449
1450     /* Take all ID's from the command packet */
1451     for (i = 0; i < argc; i++) {
1452       void *id;
1453
1454       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1455       if (!tmp)
1456         continue;
1457       
1458       idp = silc_id_payload_parse(tmp, len);
1459       if (!idp) {
1460         silc_free(*clients);
1461         silc_free(*servers);
1462         silc_free(*channels);
1463         silc_server_command_send_status_reply(
1464                                        cmd, SILC_COMMAND_IDENTIFY,
1465                                        SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1466         return 0;
1467       }
1468
1469       id = silc_id_payload_get_id(idp);
1470       
1471       switch (silc_id_payload_get_type(idp)) {
1472         
1473       case SILC_ID_CLIENT:
1474         entry = (void *)silc_idlist_find_client_by_id(server->local_list, 
1475                                                       id, TRUE, NULL);
1476         if (!entry && check_global)
1477           entry = (void *)silc_idlist_find_client_by_id(server->global_list, 
1478                                                         id, TRUE, NULL);
1479         if (entry) {
1480           *clients = silc_realloc(*clients, sizeof(**clients) * 
1481                                   (*clients_count + 1));
1482           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1483         } else {
1484           /* If we are normal server and have not resolved information from
1485              router yet, do so now. */
1486           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1487               server->server_type == SILC_SERVER && !cmd->pending && 
1488               !server->standalone) {
1489             silc_server_command_identify_send_router(cmd);
1490             silc_free(*clients);
1491             silc_free(*servers);
1492             silc_free(*channels);
1493             return -1;
1494           } else {
1495             silc_server_command_send_status_data(
1496                                         cmd, SILC_COMMAND_IDENTIFY,
1497                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1498                                         2, tmp, len);
1499             error = TRUE;
1500           }
1501         }
1502
1503         break;
1504         
1505       case SILC_ID_SERVER:
1506         entry = (void *)silc_idlist_find_server_by_id(server->local_list, 
1507                                                       id, TRUE, NULL);
1508         if (!entry && check_global)
1509           entry = (void *)silc_idlist_find_server_by_id(server->global_list, 
1510                                                         id, TRUE, NULL);
1511         if (entry) {
1512           *servers = silc_realloc(*servers, sizeof(**servers) * 
1513                                   (*servers_count + 1));
1514           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1515         } else {
1516           /* If we are normal server and have not resolved information from
1517              router yet, do so now. */
1518           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1519               server->server_type == SILC_SERVER && !cmd->pending && 
1520               !server->standalone) {
1521             silc_server_command_identify_send_router(cmd);
1522             silc_free(*clients);
1523             silc_free(*servers);
1524             silc_free(*channels);
1525             return -1;
1526           } else {
1527             silc_server_command_send_status_data(
1528                                          cmd, SILC_COMMAND_IDENTIFY,
1529                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1530                                          2, tmp, len);
1531             error = TRUE;
1532           }
1533         }
1534         break;
1535         
1536       case SILC_ID_CHANNEL:
1537         entry = (void *)silc_idlist_find_channel_by_id(server->local_list, 
1538                                                        id, NULL);
1539         if (!entry && check_global)
1540           entry = (void *)silc_idlist_find_channel_by_id(server->global_list, 
1541                                                          id, NULL);
1542         if (entry) {
1543           *channels = silc_realloc(*channels, sizeof(**channels) * 
1544                                    (*channels_count + 1));
1545           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1546         } else {
1547           /* If we are normal server and have not resolved information from
1548              router yet, do so now. */
1549           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1550               server->server_type == SILC_SERVER && !cmd->pending && 
1551               !server->standalone) {
1552             silc_server_command_identify_send_router(cmd);
1553             silc_free(*clients);
1554             silc_free(*servers);
1555             silc_free(*channels);
1556             return -1;
1557           } else {
1558             silc_server_command_send_status_data(
1559                                          cmd, SILC_COMMAND_IDENTIFY,
1560                                          SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1561                                          2, tmp, len);
1562             error = TRUE;
1563           }
1564         }
1565         break;
1566       }
1567
1568       silc_free(id);
1569     }
1570   }
1571
1572   if (error) {
1573     silc_free(*clients);
1574     silc_free(*servers);
1575     silc_free(*channels);
1576     return FALSE;
1577   }
1578   
1579   /* Get the max count of reply messages allowed */
1580   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1581   if (tmp)
1582     *count = atoi(tmp);
1583   else
1584     *count = 0;
1585
1586   return 1;
1587 }
1588
1589 /* Checks that all mandatory fields in client entry are present. If not
1590    then send WHOIS request to the server who owns the client. We use
1591    WHOIS because we want to get as much information as possible at once. */
1592
1593 static bool
1594 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1595                                           SilcClientEntry *clients,
1596                                           uint32 clients_count)
1597 {
1598   SilcServer server = cmd->server;
1599   SilcClientEntry entry;
1600   SilcServerResolveContext resolve = NULL, r = NULL;
1601   uint32 resolve_count = 0;
1602   int i, k;
1603   bool no_res = TRUE;
1604
1605   for (i = 0; i < clients_count; i++) {
1606     entry = clients[i];
1607     if (!entry)
1608       continue;
1609
1610     if (entry->nickname || 
1611         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1612       if (!entry->router)
1613         continue;
1614
1615       /* If we are normal server, and we've not resolved this client from
1616          router and it is global client, we'll check whether it is on some
1617          channel.  If not then we cannot be sure about its validity, and
1618          we'll resolve it from router. */
1619       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1620           entry->connection || silc_hash_table_count(entry->channels))
1621         continue;
1622     }
1623
1624     /* We need to resolve this entry since it is not complete */
1625
1626     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1627       /* The entry is being resolved (and we are not the resolver) so attach
1628          to the command reply and we're done with this one. */
1629       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1630                                   entry->resolve_cmd_ident,
1631                                   silc_server_command_identify,
1632                                   silc_server_command_dup(cmd));
1633       no_res = FALSE;
1634     } else {
1635       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636         /* We've resolved this and it still is not ready.  We'll return
1637            and are that this will be handled again after it is resolved. */
1638         for (i = 0; i < resolve_count; i++) {
1639           for (k = 0; k < r->res_argc; k++)
1640             silc_free(r->res_argv[k]);
1641           silc_free(r->res_argv);
1642           silc_free(r->res_argv_lens);
1643           silc_free(r->res_argv_types);
1644         }
1645         silc_free(resolve);
1646         return FALSE;
1647       } else {
1648         /* We'll resolve this client */
1649         SilcBuffer idp;
1650
1651         r = NULL;
1652         for (k = 0; k < resolve_count; k++) {
1653           if (resolve[k].router == entry->router) {
1654             r = &resolve[k];
1655             break;
1656           }
1657         }
1658
1659         if (!r) {
1660           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1661                                  (resolve_count + 1));
1662           r = &resolve[resolve_count];
1663           memset(r, 0, sizeof(*r));
1664           r->router = entry->router;
1665           r->ident = ++server->cmd_ident;
1666           resolve_count++;
1667         }
1668
1669         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1670                                    (r->res_argc + 1));
1671         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1672                                         sizeof(*r->res_argv_lens) *
1673                                         (r->res_argc + 1));
1674         r->res_argv_types = silc_realloc(r->res_argv_types, 
1675                                          sizeof(*r->res_argv_types) *
1676                                          (r->res_argc + 1));
1677         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1678         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1679                                                sizeof(**r->res_argv));
1680         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1681         r->res_argv_lens[r->res_argc] = idp->len;
1682         r->res_argv_types[r->res_argc] = r->res_argc + 3;
1683         r->res_argc++;
1684         silc_buffer_free(idp);
1685
1686         entry->resolve_cmd_ident = r->ident;
1687         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1688         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1689       }
1690     }
1691   }
1692
1693   /* Do the resolving */
1694   for (i = 0; i < resolve_count; i++) {
1695     SilcBuffer res_cmd;
1696
1697     r = &resolve[i];
1698
1699     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1700        now anyway so make it a good one. */
1701     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1702                                           r->res_argc, r->res_argv, 
1703                                           r->res_argv_lens,
1704                                           r->res_argv_types, 
1705                                           r->ident);
1706     silc_server_packet_send(server, r->router->connection,
1707                             SILC_PACKET_COMMAND, cmd->packet->flags,
1708                             res_cmd->data, res_cmd->len, FALSE);
1709
1710     /* Reprocess this packet after received reply */
1711     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1712                                 r->ident,
1713                                 silc_server_command_identify,
1714                                 silc_server_command_dup(cmd));
1715     cmd->pending = TRUE;
1716
1717     silc_buffer_free(res_cmd);
1718     for (k = 0; k < r->res_argc; k++)
1719       silc_free(r->res_argv[k]);
1720     silc_free(r->res_argv);
1721     silc_free(r->res_argv_lens);
1722     silc_free(r->res_argv_types);
1723     no_res = FALSE;
1724   }
1725   silc_free(resolve);
1726
1727   return no_res;
1728 }
1729
1730 static void
1731 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1732                                         SilcClientEntry *clients,
1733                                         uint32 clients_count,
1734                                         SilcServerEntry *servers,
1735                                         uint32 servers_count,
1736                                         SilcChannelEntry *channels,
1737                                         uint32 channels_count,
1738                                         int count)
1739 {
1740   SilcServer server = cmd->server;
1741   int i, k, len, valid_count;
1742   SilcBuffer packet, idp;
1743   SilcCommandStatus status;
1744   uint16 ident = silc_command_get_ident(cmd->payload);
1745   char nh[256], uh[256];
1746   SilcSocketConnection hsock;
1747
1748   status = SILC_STATUS_OK;
1749
1750   if (clients) {
1751     SilcClientEntry entry;
1752
1753     /* Process only valid entries. */
1754     valid_count = 0;
1755     for (i = 0; i < clients_count; i++) {
1756       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1757         valid_count++;
1758       else
1759         clients[i] = NULL;
1760     }
1761
1762     if (!valid_count) {
1763       /* No valid entries found at all, just send error */
1764       unsigned char *tmp;
1765
1766       tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1767       if (tmp) {
1768         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1769                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1770                                              3, tmp, strlen(tmp));
1771       } else {
1772         tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1773         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1774                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1775                                              2, tmp, len);
1776       }
1777       return;
1778     }
1779
1780     /* Process all valid client entries and send command replies */
1781
1782     if (valid_count > 1)
1783       status = SILC_STATUS_LIST_START;
1784
1785     for (i = 0, k = 0; i < clients_count; i++) {
1786       entry = clients[i];
1787       if (!entry)
1788         continue;
1789
1790       if (k >= 1)
1791         status = SILC_STATUS_LIST_ITEM;
1792       if (valid_count > 1 && k == valid_count - 1 
1793           && !servers_count && !channels_count)
1794         status = SILC_STATUS_LIST_END;
1795       if (count && k - 1 == count)
1796         status = SILC_STATUS_LIST_END;
1797       if (count && k - 1 > count)
1798         break;
1799
1800       /* Send IDENTIFY reply */
1801
1802       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1803       memset(uh, 0, sizeof(uh));
1804       memset(nh, 0, sizeof(nh));
1805       strncat(nh, entry->nickname, strlen(entry->nickname));
1806       if (!strchr(entry->nickname, '@')) {
1807         strncat(nh, "@", 1);
1808         if (entry->servername) {
1809           strncat(nh, entry->servername, strlen(entry->servername));
1810         } else {
1811           len = entry->router ? strlen(entry->router->server_name) :
1812             strlen(server->server_name);
1813           strncat(nh, entry->router ? entry->router->server_name :
1814                   server->server_name, len);
1815         }
1816       }
1817
1818       if (!entry->username) {
1819         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1820                                                       status, ident, 2,
1821                                                       2, idp->data, idp->len, 
1822                                                       3, nh, strlen(nh));
1823       } else {
1824         strncat(uh, entry->username, strlen(entry->username));
1825         if (!strchr(entry->username, '@')) {
1826           strncat(uh, "@", 1);
1827           hsock = (SilcSocketConnection)entry->connection;
1828           len = strlen(hsock->hostname);
1829           strncat(uh, hsock->hostname, len);
1830         }
1831         
1832         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1833                                                       status, ident, 3,
1834                                                       2, idp->data, idp->len, 
1835                                                       3, nh, strlen(nh),
1836                                                       4, uh, strlen(uh));
1837       }
1838       
1839       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1840                               0, packet->data, packet->len, FALSE);
1841       
1842       silc_buffer_free(packet);
1843       silc_buffer_free(idp);
1844       
1845       k++;
1846     }
1847   }
1848
1849   if (servers) {
1850     SilcServerEntry entry;
1851
1852     if (status == SILC_STATUS_OK && servers_count > 1)
1853       status = SILC_STATUS_LIST_START;
1854
1855     for (i = 0, k = 0; i < servers_count; i++) {
1856       entry = servers[i];
1857       
1858       if (k >= 1)
1859         status = SILC_STATUS_LIST_ITEM;
1860       if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1861         status = SILC_STATUS_LIST_END;
1862       if (count && k - 1 == count)
1863         status = SILC_STATUS_LIST_END;
1864       if (count && k - 1 > count)
1865         break;
1866       
1867       /* Send IDENTIFY reply */
1868       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1869       packet = 
1870         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1871                                              status, ident, 2,
1872                                              2, idp->data, idp->len, 
1873                                              3, entry->server_name, 
1874                                              entry->server_name ? 
1875                                              strlen(entry->server_name) : 0);
1876       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1877                               0, packet->data, packet->len, FALSE);
1878       
1879       silc_buffer_free(packet);
1880       silc_buffer_free(idp);
1881       
1882       k++;
1883     }
1884   }
1885
1886   if (channels) {
1887     SilcChannelEntry entry;
1888
1889     if (status == SILC_STATUS_OK && channels_count > 1)
1890       status = SILC_STATUS_LIST_START;
1891
1892     for (i = 0, k = 0; i < channels_count; i++) {
1893       entry = channels[i];
1894       
1895       if (k >= 1)
1896         status = SILC_STATUS_LIST_ITEM;
1897       if (channels_count > 1 && k == channels_count - 1)
1898         status = SILC_STATUS_LIST_END;
1899       if (count && k - 1 == count)
1900         status = SILC_STATUS_LIST_END;
1901       if (count && k - 1 > count)
1902         break;
1903       
1904       /* Send IDENTIFY reply */
1905       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1906       packet = 
1907         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1908                                              status, ident, 2,
1909                                              2, idp->data, idp->len, 
1910                                              3, entry->channel_name, 
1911                                              entry->channel_name ? 
1912                                              strlen(entry->channel_name): 0);
1913       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1914                               0, packet->data, packet->len, FALSE);
1915       
1916       silc_buffer_free(packet);
1917       silc_buffer_free(idp);
1918       
1919       k++;
1920     }
1921   }
1922 }
1923
1924 static int
1925 silc_server_command_identify_process(SilcServerCommandContext cmd)
1926 {
1927   uint32 count = 0;
1928   int ret = 0;
1929   SilcClientEntry *clients = NULL;
1930   SilcServerEntry *servers = NULL;
1931   SilcChannelEntry *channels = NULL;
1932   uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1933
1934   /* Parse the IDENTIFY request */
1935   ret = silc_server_command_identify_parse(cmd,
1936                                            &clients, &clients_count,
1937                                            &servers, &servers_count,
1938                                            &channels, &channels_count,
1939                                            &count);
1940   if (ret < 1)
1941     return ret;
1942   ret = 0;
1943
1944   /* Check that all mandatory fields are present and request those data
1945      from the server who owns the client if necessary. */
1946   if (clients && !silc_server_command_identify_check_client(cmd, clients, 
1947                                                             clients_count)) {
1948     ret = -1;
1949     goto out;
1950   }
1951
1952   /* Send the command reply to the client */
1953   silc_server_command_identify_send_reply(cmd, 
1954                                           clients, clients_count,
1955                                           servers, servers_count,
1956                                           channels, channels_count, 
1957                                           count);
1958
1959  out:
1960   silc_free(clients);
1961   silc_free(servers);
1962   silc_free(channels);
1963   return ret;
1964 }
1965
1966 SILC_SERVER_CMD_FUNC(identify)
1967 {
1968   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1969   int ret = 0;
1970
1971   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1972
1973   ret = silc_server_command_identify_process(cmd);
1974   silc_server_command_free(cmd);
1975 }
1976
1977 /* Server side of command NICK. Sets nickname for user. Setting
1978    nickname causes generation of a new client ID for the client. The
1979    new client ID is sent to the client after changing the nickname. */
1980
1981 SILC_SERVER_CMD_FUNC(nick)
1982 {
1983   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1984   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1985   SilcServer server = cmd->server;
1986   SilcBuffer packet, nidp, oidp = NULL;
1987   SilcClientID *new_id;
1988   uint32 nick_len;
1989   char *nick;
1990   uint16 ident = silc_command_get_ident(cmd->payload);
1991   int nickfail = 0;
1992
1993   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1994     goto out;
1995
1996   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1997
1998   /* Check nickname */
1999   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2000   if (nick_len > 128)
2001     nick[128] = '\0';
2002   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2003     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2004                                           SILC_STATUS_ERR_BAD_NICKNAME);
2005     goto out;
2006   }
2007
2008   /* Check for same nickname */
2009   if (!strcmp(client->nickname, nick)) {
2010     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2011     goto send_reply;
2012   }
2013
2014   /* Create new Client ID */
2015   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
2016                                    cmd->server->rng, 
2017                                    cmd->server->md5hash, nick,
2018                                    &new_id)) {
2019     nickfail++;
2020     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2021   }
2022
2023   /* Send notify about nickname change to our router. We send the new
2024      ID and ask to replace it with the old one. If we are router the
2025      packet is broadcasted. Send NICK_CHANGE notify. */
2026   if (!server->standalone)
2027     silc_server_send_notify_nick_change(server, server->router->connection, 
2028                                         server->server_type == SILC_SERVER ? 
2029                                         FALSE : TRUE, client->id,
2030                                         new_id);
2031
2032   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2033
2034   /* Remove old cache entry */
2035   silc_idcache_del_by_context(server->local_list->clients, client);
2036
2037   /* Free old ID */
2038   silc_free(client->id);
2039
2040   /* Save the nickname as this client is our local client */
2041   silc_free(client->nickname);
2042
2043   client->nickname = strdup(nick);
2044   client->id = new_id;
2045
2046   /* Update client cache */
2047   silc_idcache_add(server->local_list->clients, client->nickname, 
2048                    client->id, (void *)client, 0, NULL);
2049
2050   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2051
2052   /* Send NICK_CHANGE notify to the client's channels */
2053   silc_server_send_notify_on_channels(server, NULL, client, 
2054                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2055                                       oidp->data, oidp->len, 
2056                                       nidp->data, nidp->len);
2057
2058  send_reply:
2059   /* Send the new Client ID as reply command back to client */
2060   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2061                                                 SILC_STATUS_OK, ident, 1, 
2062                                                 2, nidp->data, nidp->len);
2063   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2064                           0, packet->data, packet->len, FALSE);
2065
2066   silc_buffer_free(packet);
2067   silc_buffer_free(nidp);
2068   if (oidp)
2069     silc_buffer_free(oidp);
2070   
2071  out:
2072   silc_server_command_free(cmd);
2073 }
2074
2075 /* Sends the LIST command reply */
2076
2077 static void
2078 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2079                                     SilcChannelEntry *lch, 
2080                                     uint32 lch_count,
2081                                     SilcChannelEntry *gch,
2082                                     uint32 gch_count)
2083 {
2084   int i, k;
2085   SilcBuffer packet, idp;
2086   SilcChannelEntry entry;
2087   SilcCommandStatus status;
2088   uint16 ident = silc_command_get_ident(cmd->payload);
2089   char *topic;
2090   unsigned char usercount[4];
2091   uint32 users;
2092   int valid_lcount = 0, valid_rcount = 0;
2093
2094   for (i = 0; i < lch_count; i++) {
2095     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2096       lch[i] = NULL;
2097     else
2098       valid_lcount++;
2099   }
2100   for (i = 0; i < gch_count; i++) {
2101     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2102       gch[i] = NULL;
2103     else
2104       valid_rcount++;
2105   }
2106
2107   status = SILC_STATUS_OK;
2108   if ((lch_count + gch_count) > 1)
2109     status = SILC_STATUS_LIST_START;
2110
2111   /* Local list */
2112   for (i = 0, k = 0; i < lch_count; i++) {
2113     entry = lch[i];
2114     if (!entry)
2115       continue;
2116
2117     if (k >= 1)
2118       status = SILC_STATUS_LIST_ITEM;
2119     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2120       status = SILC_STATUS_LIST_END;
2121
2122     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2123
2124     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2125       topic = "*private*";
2126       memset(usercount, 0, sizeof(usercount));
2127     } else {
2128       topic = entry->topic;
2129       users = silc_hash_table_count(entry->user_list);
2130       SILC_PUT32_MSB(users, usercount);
2131     }
2132
2133     /* Send the reply */
2134     packet = 
2135       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2136                                            status, ident, 4,
2137                                            2, idp->data, idp->len,
2138                                            3, entry->channel_name, 
2139                                            strlen(entry->channel_name),
2140                                            4, topic, topic ? strlen(topic) : 0,
2141                                            5, usercount, 4);
2142     silc_server_packet_send(cmd->server, cmd->sock, 
2143                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2144                             packet->len, FALSE);
2145     silc_buffer_free(packet);
2146     silc_buffer_free(idp);
2147     k++;
2148   }
2149
2150   /* Global list */
2151   for (i = 0, k = 0; i < gch_count; i++) {
2152     entry = gch[i];
2153     if (!entry)
2154       continue;
2155
2156     if (k >= 1)
2157       status = SILC_STATUS_LIST_ITEM;
2158     if (valid_rcount > 1 && k == valid_rcount - 1)
2159       status = SILC_STATUS_LIST_END;
2160
2161     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2162
2163     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2164       topic = "*private*";
2165       memset(usercount, 0, sizeof(usercount));
2166     } else {
2167       topic = entry->topic;
2168       users = entry->user_count;
2169       SILC_PUT32_MSB(users, usercount);
2170     }
2171
2172     /* Send the reply */
2173     packet = 
2174       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2175                                            status, ident, 4,
2176                                            2, idp->data, idp->len,
2177                                            3, entry->channel_name, 
2178                                            strlen(entry->channel_name),
2179                                            4, topic, topic ? strlen(topic) : 0,
2180                                            5, usercount, 4);
2181     silc_server_packet_send(cmd->server, cmd->sock, 
2182                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2183                             packet->len, FALSE);
2184     silc_buffer_free(packet);
2185     silc_buffer_free(idp);
2186     k++;
2187   }
2188 }
2189
2190 /* Server side of LIST command. This lists the channel of the requested
2191    server. Secret channels are not listed. */
2192
2193 SILC_SERVER_CMD_FUNC(list)
2194 {
2195   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2196   SilcServer server = cmd->server;
2197   SilcChannelID *channel_id = NULL;
2198   unsigned char *tmp;
2199   uint32 tmp_len;
2200   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2201   uint32 lch_count = 0, gch_count = 0;
2202
2203   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2204
2205   /* If we are normal server, send the command to router, since we
2206      want to know all channels in the network. */
2207   if (!cmd->pending && server->server_type == SILC_SERVER && 
2208       !server->standalone) {
2209     SilcBuffer tmpbuf;
2210     uint16 old_ident;
2211     
2212     old_ident = silc_command_get_ident(cmd->payload);
2213     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2214     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2215     silc_server_packet_send(server, server->router->connection,
2216                             SILC_PACKET_COMMAND, cmd->packet->flags,
2217                             tmpbuf->data, tmpbuf->len, TRUE);
2218
2219     /* Reprocess this packet after received reply from router */
2220     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2221                                 silc_command_get_ident(cmd->payload),
2222                                 silc_server_command_list, 
2223                                 silc_server_command_dup(cmd));
2224     cmd->pending = TRUE;
2225     silc_command_set_ident(cmd->payload, old_ident);
2226     silc_buffer_free(tmpbuf);
2227     goto out;
2228   }
2229
2230   /* Get Channel ID */
2231   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2232   if (tmp) {
2233     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2234     if (!channel_id) {
2235       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2236                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2237       goto out;
2238     }
2239   }
2240
2241   /* Get the channels from local list */
2242   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2243                                        &lch_count);
2244   
2245   /* Get the channels from global list */
2246   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2247                                        &gch_count);
2248
2249   /* Send the reply */
2250   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2251                                       gchannels, gch_count);
2252
2253   silc_free(lchannels);
2254   silc_free(gchannels);
2255
2256  out:
2257   silc_server_command_free(cmd);
2258 }
2259
2260 /* Server side of TOPIC command. Sets topic for channel and/or returns
2261    current topic to client. */
2262
2263 SILC_SERVER_CMD_FUNC(topic)
2264 {
2265   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2266   SilcServer server = cmd->server;
2267   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2268   SilcChannelID *channel_id;
2269   SilcChannelEntry channel;
2270   SilcChannelClientEntry chl;
2271   SilcBuffer packet, idp;
2272   unsigned char *tmp;
2273   uint32 argc, tmp_len;
2274   uint16 ident = silc_command_get_ident(cmd->payload);
2275
2276   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2277
2278   argc = silc_argument_get_arg_num(cmd->args);
2279
2280   /* Get Channel ID */
2281   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2282   if (!tmp) {
2283     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2285     goto out;
2286   }
2287   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2288   if (!channel_id) {
2289     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2290                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2291     goto out;
2292   }
2293
2294   /* Check whether the channel exists */
2295   channel = silc_idlist_find_channel_by_id(server->local_list, 
2296                                            channel_id, NULL);
2297   if (!channel) {
2298     channel = silc_idlist_find_channel_by_id(server->global_list, 
2299                                              channel_id, NULL);
2300     if (!channel) {
2301       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2302                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2303       goto out;
2304     }
2305   }
2306
2307   if (argc > 1) {
2308     /* Get the topic */
2309     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2310     if (!tmp) {
2311       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2312                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2313       goto out;
2314     }
2315
2316     if (strlen(tmp) > 256) {
2317       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2318                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2319       goto out;
2320     }
2321
2322     /* See whether the client is on channel and has rights to change topic */
2323     if (!silc_hash_table_find(channel->user_list, client, NULL, 
2324                               (void *)&chl)) {
2325       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2326                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2327       goto out;
2328     }
2329
2330     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2331       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2332         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2333                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2334         goto out;
2335       }
2336     }
2337
2338     /* Set the topic for channel */
2339     silc_free(channel->topic);
2340     channel->topic = strdup(tmp);
2341
2342     /* Send TOPIC_SET notify type to the network */
2343     if (!server->standalone)
2344       silc_server_send_notify_topic_set(server, server->router->connection,
2345                                         server->server_type == SILC_ROUTER ?
2346                                         TRUE : FALSE, channel, 
2347                                         client->id, SILC_ID_CLIENT,
2348                                         channel->topic);
2349
2350     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2351
2352     /* Send notify about topic change to all clients on the channel */
2353     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2354                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2355                                        idp->data, idp->len,
2356                                        channel->topic, strlen(channel->topic));
2357     silc_buffer_free(idp);
2358   }
2359
2360   /* Send the topic to client as reply packet */
2361   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2362   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2363                                                 SILC_STATUS_OK, ident, 2, 
2364                                                 2, idp->data, idp->len,
2365                                                 3, channel->topic, 
2366                                                 channel->topic ? 
2367                                                 strlen(channel->topic) : 0);
2368   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2369                           0, packet->data, packet->len, FALSE);
2370
2371   silc_buffer_free(packet);
2372   silc_buffer_free(idp);
2373   silc_free(channel_id);
2374
2375  out:
2376   silc_server_command_free(cmd);
2377 }
2378
2379 /* Server side of INVITE command. Invites some client to join some channel. 
2380    This command is also used to manage the invite list of the channel. */
2381
2382 SILC_SERVER_CMD_FUNC(invite)
2383 {
2384   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2385   SilcServer server = cmd->server;
2386   SilcSocketConnection sock = cmd->sock, dest_sock;
2387   SilcChannelClientEntry chl;
2388   SilcClientEntry sender, dest;
2389   SilcClientID *dest_id = NULL;
2390   SilcChannelEntry channel;
2391   SilcChannelID *channel_id = NULL;
2392   SilcIDListData idata;
2393   SilcBuffer idp, idp2, packet;
2394   unsigned char *tmp, *add, *del;
2395   uint32 len;
2396   uint16 ident = silc_command_get_ident(cmd->payload);
2397
2398   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2399
2400   /* Get Channel ID */
2401   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2402   if (!tmp) {
2403     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2405     goto out;
2406   }
2407   channel_id = silc_id_payload_parse_id(tmp, len);
2408   if (!channel_id) {
2409     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2410                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2411     goto out;
2412   }
2413
2414   /* Get the channel entry */
2415   channel = silc_idlist_find_channel_by_id(server->local_list, 
2416                                            channel_id, NULL);
2417   if (!channel) {
2418     channel = silc_idlist_find_channel_by_id(server->global_list, 
2419                                              channel_id, NULL);
2420     if (!channel) {
2421       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2422                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2423       goto out;
2424     }
2425   }
2426
2427   /* Check whether the sender of this command is on the channel. */
2428   sender = (SilcClientEntry)sock->user_data;
2429   if (!silc_server_client_on_channel(sender, channel)) {
2430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2431                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2432     goto out;
2433   }
2434
2435   /* Check whether the channel is invite-only channel. If yes then the
2436      sender of this command must be at least channel operator. */
2437   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2438     silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2439     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2440       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2442       goto out;
2443     }
2444   }
2445
2446   /* Get destination client ID */
2447   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2448   if (tmp) {
2449     char invite[512];
2450     bool resolve;
2451
2452     dest_id = silc_id_payload_parse_id(tmp, len);
2453     if (!dest_id) {
2454       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2455                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2456       goto out;
2457     }
2458
2459     /* Get the client entry */
2460     dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2461     if (!dest) {
2462       if (server->server_type != SILC_SERVER || !resolve) {
2463         silc_server_command_send_status_reply(
2464                                         cmd, SILC_COMMAND_INVITE,
2465                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2466         goto out;
2467       }
2468       
2469       /* The client info is being resolved. Reprocess this packet after
2470          receiving the reply to the query. */
2471       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2472                                   server->cmd_ident,
2473                                   silc_server_command_invite, 
2474                                   silc_server_command_dup(cmd));
2475       cmd->pending = TRUE;
2476       silc_free(channel_id);
2477       silc_free(dest_id);
2478       goto out;
2479     }
2480
2481     /* Check whether the requested client is already on the channel. */
2482     if (silc_server_client_on_channel(dest, channel)) {
2483       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2484                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2485       goto out;
2486     }
2487     
2488     /* Get route to the client */
2489     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2490     if (!dest_sock) {
2491       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2493       goto out;
2494     }
2495
2496     memset(invite, 0, sizeof(invite));
2497     strncat(invite, dest->nickname, strlen(dest->nickname));
2498     strncat(invite, "!", 1);
2499     strncat(invite, dest->username, strlen(dest->username));
2500     if (!strchr(dest->username, '@')) {
2501       strncat(invite, "@", 1);
2502       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2503     }
2504
2505     len = strlen(invite);
2506     if (!channel->invite_list)
2507       channel->invite_list = silc_calloc(len + 2, 
2508                                          sizeof(*channel->invite_list));
2509     else
2510       channel->invite_list = silc_realloc(channel->invite_list, 
2511                                           sizeof(*channel->invite_list) * 
2512                                           (len + 
2513                                            strlen(channel->invite_list) + 2));
2514     strncat(channel->invite_list, invite, len);
2515     strncat(channel->invite_list, ",", 1);
2516
2517     /* Send notify to the client that is invited to the channel */
2518     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2519     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2520     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2521                                  SILC_ID_CLIENT,
2522                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2523                                  idp->data, idp->len, 
2524                                  channel->channel_name, 
2525                                  strlen(channel->channel_name),
2526                                  idp2->data, idp2->len);
2527     silc_buffer_free(idp);
2528     silc_buffer_free(idp2);
2529   }
2530
2531   /* Add the client to the invite list of the channel */
2532   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2533   if (add) {
2534     if (!channel->invite_list)
2535       channel->invite_list = silc_calloc(len + 2, 
2536                                          sizeof(*channel->invite_list));
2537     else
2538       channel->invite_list = silc_realloc(channel->invite_list, 
2539                                           sizeof(*channel->invite_list) * 
2540                                           (len + 
2541                                            strlen(channel->invite_list) + 2));
2542     if (add[len - 1] == ',')
2543       add[len - 1] = '\0';
2544     
2545     strncat(channel->invite_list, add, len);
2546     strncat(channel->invite_list, ",", 1);
2547   }
2548
2549   /* Get the invite to be removed and remove it from the list */
2550   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2551   if (del && channel->invite_list) {
2552     char *start, *end, *n;
2553
2554     if (!strncmp(channel->invite_list, del, 
2555                  strlen(channel->invite_list) - 1)) {
2556       silc_free(channel->invite_list);
2557       channel->invite_list = NULL;
2558     } else {
2559       start = strstr(channel->invite_list, del);
2560       if (start && strlen(start) >= len) {
2561         end = start + len;
2562         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2563         strncat(n, channel->invite_list, start - channel->invite_list);
2564         strncat(n, end + 1, ((channel->invite_list + 
2565                               strlen(channel->invite_list)) - end) - 1);
2566         silc_free(channel->invite_list);
2567         channel->invite_list = n;
2568       }
2569     }
2570   }
2571
2572   /* Send notify to the primary router */
2573   if (!server->standalone)
2574     silc_server_send_notify_invite(server, server->router->connection,
2575                                    server->server_type == SILC_ROUTER ?
2576                                    TRUE : FALSE, channel,
2577                                    sender->id, add, del);
2578
2579   /* Send command reply */
2580   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2581
2582   if (add || del)
2583     packet = 
2584       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2585                                            SILC_STATUS_OK, ident, 2,
2586                                            2, tmp, len,
2587                                            3, channel->invite_list,
2588                                            channel->invite_list ?
2589                                            strlen(channel->invite_list) : 0);
2590   else
2591     packet = 
2592       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2593                                            SILC_STATUS_OK, ident, 1,
2594                                            2, tmp, len);
2595   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2596                           packet->data, packet->len, FALSE);
2597   silc_buffer_free(packet);
2598
2599  out:
2600   silc_free(dest_id);
2601   silc_free(channel_id);
2602   silc_server_command_free(cmd);
2603 }
2604
2605 typedef struct {
2606   SilcServer server;
2607   SilcSocketConnection sock;
2608   char *signoff;
2609 } *QuitInternal;
2610
2611 /* Quits connection to client. This gets called if client won't
2612    close the connection even when it has issued QUIT command. */
2613
2614 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2615 {
2616   QuitInternal q = (QuitInternal)context;
2617
2618   /* Free all client specific data, such as client entry and entires
2619      on channels this client may be on. */
2620   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2621                                TRUE, q->signoff);
2622   q->sock->user_data = NULL;
2623
2624   /* Close the connection on our side */
2625   silc_server_close_connection(q->server, q->sock);
2626
2627   silc_free(q->signoff);
2628   silc_free(q);
2629 }
2630
2631 /* Quits SILC session. This is the normal way to disconnect client. */
2632  
2633 SILC_SERVER_CMD_FUNC(quit)
2634 {
2635   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636   SilcServer server = cmd->server;
2637   SilcSocketConnection sock = cmd->sock;
2638   QuitInternal q;
2639   unsigned char *tmp = NULL;
2640   uint32 len = 0;
2641
2642   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2643
2644   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2645     goto out;
2646
2647   /* Get destination ID */
2648   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2649   if (len > 128)
2650     tmp = NULL;
2651
2652   q = silc_calloc(1, sizeof(*q));
2653   q->server = server;
2654   q->sock = sock;
2655   q->signoff = tmp ? strdup(tmp) : NULL;
2656
2657   /* We quit the connection with little timeout */
2658   silc_schedule_task_add(server->schedule, sock->sock,
2659                      silc_server_command_quit_cb, (void *)q,
2660                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2661
2662  out:
2663   silc_server_command_free(cmd);
2664 }
2665
2666 /* Server side of command KILL. This command is used by router operator
2667    to remove an client from the SILC Network temporarily. */
2668
2669 SILC_SERVER_CMD_FUNC(kill)
2670 {
2671   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672   SilcServer server = cmd->server;
2673   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2674   SilcClientEntry remote_client;
2675   SilcClientID *client_id;
2676   unsigned char *tmp, *comment;
2677   uint32 tmp_len, tmp_len2;
2678   bool local;
2679
2680   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2681
2682   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2683     goto out;
2684
2685   /* KILL command works only on router */
2686   if (server->server_type != SILC_ROUTER) {
2687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2689     goto out;
2690   }
2691
2692   /* Check whether client has the permissions. */
2693   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2694     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2696     goto out;
2697   }
2698
2699   /* Get the client ID */
2700   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2701   if (!tmp) {
2702     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2703                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2704     goto out;
2705   }
2706   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2707   if (!client_id) {
2708     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2710     goto out;
2711   }
2712
2713   /* Get the client entry */
2714   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2715                                                 client_id, TRUE, NULL);
2716   local = TRUE;
2717   if (!remote_client) {
2718     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2719                                                   client_id, TRUE, NULL);
2720     local = FALSE;
2721     if (!remote_client) {
2722       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2724       goto out;
2725     }
2726   }
2727
2728   /* Get comment */
2729   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2730   if (tmp_len2 > 128)
2731     comment = NULL;
2732
2733   /* Send reply to the sender */
2734   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2735                                         SILC_STATUS_OK);
2736
2737   /* Send the KILL notify packets. First send it to the channel, then
2738      to our primary router and then directly to the client who is being
2739      killed right now. */
2740
2741   /* Send KILLED notify to the channels. It is not sent to the client
2742      as it will be sent differently destined directly to the client and not
2743      to the channel. */
2744   silc_server_send_notify_on_channels(server, remote_client, 
2745                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2746                                       comment ? 2 : 1,
2747                                       tmp, tmp_len,
2748                                       comment, comment ? tmp_len2 : 0);
2749
2750   /* Send KILLED notify to primary route */
2751   if (!server->standalone)
2752     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2753                                    remote_client->id, comment);
2754
2755   /* Send KILLED notify to the client directly */
2756   silc_server_send_notify_killed(server, remote_client->connection ? 
2757                                  remote_client->connection : 
2758                                  remote_client->router->connection, FALSE,
2759                                  remote_client->id, comment);
2760
2761   /* Remove the client from all channels. This generates new keys to the
2762      channels as well. */
2763   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2764                                    NULL, TRUE);
2765
2766   /* Remove the client entry, If it is locally connected then we will also
2767      disconnect the client here */
2768   if (remote_client->connection) {
2769     /* Remove locally conneted client */
2770     SilcSocketConnection sock = remote_client->connection;
2771     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2772     silc_server_close_connection(server, sock);
2773   } else {
2774     /* Update statistics */
2775     if (remote_client->connection)
2776       server->stat.my_clients--;
2777     if (server->server_type == SILC_ROUTER)
2778       server->stat.cell_clients--;
2779     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2780     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2781
2782     /* Remove remote client */
2783     silc_idlist_del_client(local ? server->local_list :
2784                            server->global_list, remote_client);
2785   }
2786
2787  out:
2788   silc_server_command_free(cmd);
2789 }
2790
2791 /* Server side of command INFO. This sends information about us to 
2792    the client. If client requested specific server we will send the 
2793    command to that server. */
2794
2795 SILC_SERVER_CMD_FUNC(info)
2796 {
2797   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2798   SilcServer server = cmd->server;
2799   SilcBuffer packet, idp;
2800   unsigned char *tmp;
2801   uint32 tmp_len;
2802   char *dest_server, *server_info = NULL, *server_name;
2803   uint16 ident = silc_command_get_ident(cmd->payload);
2804   SilcServerEntry entry = NULL;
2805   SilcServerID *server_id = NULL;
2806
2807   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2808
2809   /* Get server name */
2810   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2811
2812   /* Get Server ID */
2813   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2814   if (tmp) {
2815     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2816     if (!server_id) {
2817       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2818                                             SILC_STATUS_ERR_NO_SERVER_ID);
2819       goto out;
2820     }
2821   }
2822
2823   if (server_id) {
2824     /* Check whether we have this server cached */
2825     entry = silc_idlist_find_server_by_id(server->local_list,
2826                                           server_id, TRUE, NULL);
2827     if (!entry) {
2828       entry = silc_idlist_find_server_by_id(server->global_list,
2829                                             server_id, TRUE, NULL);
2830       if (!entry && server->server_type != SILC_SERVER) {
2831         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2832                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2833         goto out;
2834       }
2835     }
2836   }
2837
2838   /* Some buggy servers has sent request to router about themselves. */
2839   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2840     goto out;
2841
2842   if ((!dest_server && !server_id && !entry) || (entry && 
2843                                                  entry == server->id_entry) ||
2844       (dest_server && !cmd->pending && 
2845        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2846     /* Send our reply */
2847     char info_string[256];
2848
2849     memset(info_string, 0, sizeof(info_string));
2850     snprintf(info_string, sizeof(info_string), 
2851              "location: %s server: %s admin: %s <%s>",
2852              server->config->server_info->location,
2853              server->config->server_info->server_type,
2854              server->config->server_info->admin,
2855              server->config->server_info->email);
2856
2857     server_info = info_string;
2858     entry = server->id_entry;
2859   } else {
2860     /* Check whether we have this server cached */
2861     if (!entry && dest_server) {
2862       entry = silc_idlist_find_server_by_name(server->global_list,
2863                                               dest_server, TRUE, NULL);
2864       if (!entry) {
2865         entry = silc_idlist_find_server_by_name(server->local_list,
2866                                                 dest_server, TRUE, NULL);
2867       }
2868     }
2869
2870     if (!cmd->pending &&
2871         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2872       /* Send to the server */
2873       SilcBuffer tmpbuf;
2874       uint16 old_ident;
2875
2876       old_ident = silc_command_get_ident(cmd->payload);
2877       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2878       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2879
2880       silc_server_packet_send(server, entry->connection,
2881                               SILC_PACKET_COMMAND, cmd->packet->flags,
2882                               tmpbuf->data, tmpbuf->len, TRUE);
2883
2884       /* Reprocess this packet after received reply from router */
2885       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2886                                   silc_command_get_ident(cmd->payload),
2887                                   silc_server_command_info,
2888                                   silc_server_command_dup(cmd));
2889       cmd->pending = TRUE;
2890       silc_command_set_ident(cmd->payload, old_ident);
2891       silc_buffer_free(tmpbuf);
2892       goto out;
2893     }
2894
2895     if (!entry && !cmd->pending && !server->standalone) {
2896       /* Send to the primary router */
2897       SilcBuffer tmpbuf;
2898       uint16 old_ident;
2899
2900       old_ident = silc_command_get_ident(cmd->payload);
2901       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2902       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2903
2904       silc_server_packet_send(server, server->router->connection,
2905                               SILC_PACKET_COMMAND, cmd->packet->flags,
2906                               tmpbuf->data, tmpbuf->len, TRUE);
2907
2908       /* Reprocess this packet after received reply from router */
2909       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2910                                   silc_command_get_ident(cmd->payload),
2911                                   silc_server_command_info,
2912                                   silc_server_command_dup(cmd));
2913       cmd->pending = TRUE;
2914       silc_command_set_ident(cmd->payload, old_ident);
2915       silc_buffer_free(tmpbuf);
2916       goto out;
2917     }
2918   }
2919
2920   silc_free(server_id);
2921
2922   if (!entry) {
2923     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2924                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2925     goto out;
2926   }
2927
2928   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2929   if (!server_info)
2930     server_info = entry->server_info;
2931   server_name = entry->server_name;
2932
2933   /* Send the reply */
2934   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2935                                                 SILC_STATUS_OK, ident, 3,
2936                                                 2, idp->data, idp->len,
2937                                                 3, server_name, 
2938                                                 strlen(server_name),
2939                                                 4, server_info, 
2940                                                 server_info ? 
2941                                                 strlen(server_info) : 0);
2942   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2943                           packet->data, packet->len, FALSE);
2944     
2945   silc_buffer_free(packet);
2946   silc_buffer_free(idp);
2947
2948  out:
2949   silc_server_command_free(cmd);
2950 }
2951
2952 /* Server side of command PING. This just replies to the ping. */
2953
2954 SILC_SERVER_CMD_FUNC(ping)
2955 {
2956   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2957   SilcServer server = cmd->server;
2958   SilcServerID *id;
2959   uint32 len;
2960   unsigned char *tmp;
2961
2962   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2963
2964   /* Get Server ID */
2965   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2966   if (!tmp) {
2967     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2968                                           SILC_STATUS_ERR_NO_SERVER_ID);
2969     goto out;
2970   }
2971   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2972   if (!id)
2973     goto out;
2974
2975   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2976     /* Send our reply */
2977     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2978                                           SILC_STATUS_OK);
2979   } else {
2980     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2981                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2982     goto out;
2983   }
2984
2985   silc_free(id);
2986
2987  out:
2988   silc_server_command_free(cmd);
2989 }
2990
2991 /* Internal routine to join channel. The channel sent to this function
2992    has been either created or resolved from ID lists. This joins the sent
2993    client to the channel. */
2994
2995 static void silc_server_command_join_channel(SilcServer server, 
2996                                              SilcServerCommandContext cmd,
2997                                              SilcChannelEntry channel,
2998                                              SilcClientID *client_id,
2999                                              bool created,
3000                                              bool create_key,
3001                                              uint32 umode,
3002                                              const unsigned char *auth,
3003                                              uint32 auth_len)
3004 {
3005   SilcSocketConnection sock = cmd->sock;
3006   unsigned char *tmp;
3007   uint32 tmp_len, user_count;
3008   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3009   SilcClientEntry client;
3010   SilcChannelClientEntry chl;
3011   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3012   uint16 ident = silc_command_get_ident(cmd->payload);
3013   char check[512], check2[512];
3014   bool founder = FALSE;
3015   bool resolve;
3016
3017   SILC_LOG_DEBUG(("Start"));
3018
3019   if (!channel)
3020     return;
3021
3022   /* Get the client entry */
3023   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3024     client = (SilcClientEntry)sock->user_data;
3025   } else {
3026     client = silc_server_get_client_resolve(server, client_id, &resolve);
3027     if (!client) {
3028       if (cmd->pending)
3029         goto out;
3030
3031       if (!resolve) {
3032         silc_server_command_send_status_reply(
3033                                          cmd, SILC_COMMAND_JOIN,
3034                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3035         goto out;
3036       }
3037
3038       /* The client info is being resolved. Reprocess this packet after
3039          receiving the reply to the query. */
3040       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3041                                   server->cmd_ident,
3042                                   silc_server_command_join, 
3043                                   silc_server_command_dup(cmd));
3044       cmd->pending = TRUE;
3045       goto out;
3046     }
3047
3048     cmd->pending = FALSE;
3049   }
3050
3051   /*
3052    * Check founder auth payload if provided.  If client can gain founder
3053    * privileges it can override various conditions on joining the channel,
3054    * and can have directly the founder mode set on the channel.
3055    */
3056   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3057     SilcIDListData idata = (SilcIDListData)client;
3058
3059     if (channel->founder_key && idata->public_key &&
3060         silc_pkcs_public_key_compare(channel->founder_key, 
3061                                      idata->public_key)) {
3062       void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3063                          (void *)channel->founder_passwd : 
3064                          (void *)channel->founder_key);
3065       uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3066                               channel->founder_passwd_len : 0);
3067
3068       /* Check whether the client is to become founder */
3069       if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
3070                                 auth_data, auth_data_len,
3071                                 idata->hash, client->id, SILC_ID_CLIENT)) {
3072         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3073         founder = TRUE;
3074       }
3075     }
3076   }
3077
3078   /*
3079    * Check channel modes
3080    */
3081
3082   if (!umode) {
3083     memset(check, 0, sizeof(check));
3084     memset(check2, 0, sizeof(check2));
3085     strncat(check, client->nickname, strlen(client->nickname));
3086     strncat(check, "!", 1);
3087     strncat(check, client->username, strlen(client->username));
3088     if (!strchr(client->username, '@')) {
3089       strncat(check, "@", 1);
3090       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3091     }
3092
3093     strncat(check2, client->nickname, strlen(client->nickname));
3094     if (!strchr(client->nickname, '@')) {
3095       strncat(check2, "@", 1);
3096       strncat(check2, server->server_name, strlen(server->server_name));
3097     }
3098     strncat(check2, "!", 1);
3099     strncat(check2, client->username, strlen(client->username));
3100     if (!strchr(client->username, '@')) {
3101       strncat(check2, "@", 1);
3102       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3103     }
3104     
3105     /* Check invite list if channel is invite-only channel */
3106     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3107       if (!channel->invite_list ||
3108           (!silc_string_match(channel->invite_list, check) &&
3109            !silc_string_match(channel->invite_list, check2))) {
3110         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3111                                               SILC_STATUS_ERR_NOT_INVITED);
3112         goto out;
3113       }
3114     }
3115
3116     /* Check ban list if it exists. If the client's nickname, server,
3117        username and/or hostname is in the ban list the access to the
3118        channel is denied. */
3119     if (channel->ban_list) {
3120       if (silc_string_match(channel->ban_list, check) ||
3121           silc_string_match(channel->ban_list, check2)) {
3122         silc_server_command_send_status_reply(
3123                                       cmd, SILC_COMMAND_JOIN,
3124                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3125         goto out;
3126       }
3127     }
3128     
3129     /* Check user count limit if set. */
3130     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3131       if (silc_hash_table_count(channel->user_list) + 1 > 
3132           channel->user_limit) {
3133         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3134                                               SILC_STATUS_ERR_CHANNEL_IS_FULL);
3135         goto out;
3136       }
3137     }
3138   }
3139
3140   /* Check the channel passphrase if set. */
3141   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3142     /* Get passphrase */
3143     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3144     if (tmp) {
3145       passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3146       memcpy(passphrase, tmp, tmp_len);
3147     }
3148   
3149     if (!passphrase || !channel->passphrase ||
3150         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3151       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3152                                             SILC_STATUS_ERR_BAD_PASSWORD);
3153       goto out;
3154     }
3155   }
3156
3157   /*
3158    * Client is allowed to join to the channel. Make it happen.
3159    */
3160
3161   /* Check whether the client already is on the channel */
3162   if (silc_server_client_on_channel(client, channel)) {
3163     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3164                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3165     goto out;
3166   }
3167
3168   /* Generate new channel key as protocol dictates */
3169   if (create_key) {
3170     if (!silc_server_create_channel_key(server, channel, 0))
3171       goto out;
3172
3173     /* Send the channel key. This is broadcasted to the channel but is not
3174        sent to the client who is joining to the channel. */
3175     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3176       silc_server_send_channel_key(server, NULL, channel, 
3177                                    server->server_type == SILC_ROUTER ? 
3178                                    FALSE : !server->standalone);
3179   }
3180
3181   /* Join the client to the channel by adding it to channel's user list.
3182      Add also the channel to client entry's channels list for fast cross-
3183      referencing. */
3184   chl = silc_calloc(1, sizeof(*chl));
3185   chl->mode = umode;
3186   chl->client = client;
3187   chl->channel = channel;
3188   silc_hash_table_add(channel->user_list, client, chl);
3189   silc_hash_table_add(client->channels, channel, chl);
3190   channel->user_count++;
3191
3192   /* Get users on the channel */
3193   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3194                                    &user_count);
3195
3196   /* Encode Client ID Payload of the original client who wants to join */
3197   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3198
3199   /* Encode command reply packet */
3200   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3201   SILC_PUT32_MSB(channel->mode, mode);
3202   SILC_PUT32_MSB(created, tmp2);
3203   SILC_PUT32_MSB(user_count, tmp3);
3204
3205   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3206     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3207     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3208                                            strlen(channel->channel_key->
3209                                                   cipher->name),
3210                                            channel->channel_key->cipher->name,
3211                                            channel->key_len / 8, channel->key);
3212     silc_free(tmp);
3213   }
3214
3215   reply = 
3216     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3217                                          SILC_STATUS_OK, ident, 13,
3218                                          2, channel->channel_name,
3219                                          strlen(channel->channel_name),
3220                                          3, chidp->data, chidp->len,
3221                                          4, clidp->data, clidp->len,
3222                                          5, mode, 4,
3223                                          6, tmp2, 4,
3224                                          7, keyp ? keyp->data : NULL, 
3225                                          keyp ? keyp->len : 0,
3226                                          8, channel->ban_list, 
3227                                          channel->ban_list ?
3228                                          strlen(channel->ban_list) : 0,
3229                                          9, channel->invite_list,
3230                                          channel->invite_list ?
3231                                          strlen(channel->invite_list) : 0,
3232                                          10, channel->topic,
3233                                          channel->topic ?
3234                                          strlen(channel->topic) : 0,
3235                                          11, silc_hmac_get_name(channel->hmac),
3236                                          strlen(silc_hmac_get_name(channel->
3237                                                                    hmac)),
3238                                          12, tmp3, 4,
3239                                          13, user_list->data, user_list->len,
3240                                          14, mode_list->data, 
3241                                          mode_list->len);
3242
3243   /* Send command reply */
3244   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3245                           reply->data, reply->len, FALSE);
3246
3247   /* Send JOIN notify to locally connected clients on the channel. If
3248      we are normal server then router will send or have sent JOIN notify
3249      already. However since we've added the client already to our channel
3250      we'll ignore it (in packet_receive.c) so we must send it here. If
3251      we are router then this will send it to local clients and local
3252      servers. */
3253   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3254                                      SILC_NOTIFY_TYPE_JOIN, 2,
3255                                      clidp->data, clidp->len,
3256                                      chidp->data, chidp->len);
3257
3258   if (!cmd->pending) {
3259     /* Send JOIN notify packet to our primary router */
3260     if (!server->standalone)
3261       silc_server_send_notify_join(server, server->router->connection,
3262                                    server->server_type == SILC_ROUTER ?
3263                                    TRUE : FALSE, channel, client->id);
3264
3265     if (keyp)
3266       /* Distribute the channel key to all backup routers. */
3267       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3268                               keyp->data, keyp->len, FALSE, TRUE);
3269   }
3270
3271   /* If client became founder by providing correct founder auth data
3272      notify the mode change to the channel. */
3273   if (founder) {
3274     SILC_PUT32_MSB(chl->mode, mode);
3275     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3276                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3277                                        clidp->data, clidp->len,
3278                                        mode, 4, clidp->data, clidp->len);
3279       
3280     /* Set CUMODE notify type to network */
3281     if (!server->standalone)
3282       silc_server_send_notify_cumode(server, server->router->connection,
3283                                      server->server_type == SILC_ROUTER ? 
3284                                      TRUE : FALSE, channel,
3285                                      chl->mode, client->id, SILC_ID_CLIENT,
3286                                      client->id);
3287   }
3288
3289   silc_buffer_free(reply);
3290   silc_buffer_free(clidp);
3291   silc_buffer_free(chidp);
3292   silc_buffer_free(keyp);
3293   silc_buffer_free(user_list);
3294   silc_buffer_free(mode_list);
3295
3296  out:
3297   silc_free(passphrase);
3298 }
3299
3300 /* Server side of command JOIN. Joins client into requested channel. If 
3301    the channel does not exist it will be created. */
3302
3303 SILC_SERVER_CMD_FUNC(join)
3304 {
3305   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3306   SilcServer server = cmd->server;
3307   unsigned char *auth;
3308   uint32 tmp_len, auth_len;
3309   char *tmp, *channel_name = NULL, *cipher, *hmac;
3310   SilcChannelEntry channel;
3311   uint32 umode = 0;
3312   bool created = FALSE, create_key = TRUE;
3313   SilcClientID *client_id;
3314
3315   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3316
3317   /* Get channel name */
3318   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3319   if (!tmp) {
3320     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3321                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3322     goto out;
3323   }
3324   channel_name = tmp;
3325
3326   if (tmp_len > 256)
3327     channel_name[255] = '\0';
3328
3329   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3330     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331                                           SILC_STATUS_ERR_BAD_CHANNEL);
3332     goto out;
3333   }
3334
3335   /* Get Client ID of the client who is joining to the channel */
3336   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3337   if (!tmp) {
3338     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3339                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3340     goto out;
3341   }
3342   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3343   if (!client_id) {
3344     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3345                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3346     goto out;
3347   }
3348
3349   /* Get cipher, hmac name and auth payload */
3350   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3351   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3352   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3353
3354   /* See if the channel exists */
3355   channel = silc_idlist_find_channel_by_name(server->local_list, 
3356                                              channel_name, NULL);
3357
3358   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3359     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3360     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3361
3362     if (!channel || channel->disabled) {
3363       /* Channel not found */
3364
3365       /* If we are standalone server we don't have a router, we just create 
3366          the channel by ourselves. */
3367       if (server->standalone) {
3368         channel = silc_server_create_new_channel(server, server->id, cipher, 
3369                                                  hmac, channel_name, TRUE);
3370         if (!channel) {
3371           silc_server_command_send_status_reply(
3372                                          cmd, SILC_COMMAND_JOIN,
3373                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3374           goto out;
3375         }
3376         
3377         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3378         created = TRUE;
3379         create_key = FALSE;
3380         
3381       } else {
3382
3383         /* The channel does not exist on our server. If we are normal server 
3384            we will send JOIN command to our router which will handle the
3385            joining procedure (either creates the channel if it doesn't exist 
3386            or joins the client to it). */
3387         if (server->server_type != SILC_ROUTER) {
3388           SilcBuffer tmpbuf;
3389           uint16 old_ident;
3390
3391           /* If this is pending command callback then we've resolved
3392              it and it didn't work, return since we've notified the
3393              client already in the command reply callback. */
3394           if (cmd->pending)
3395             goto out;
3396           
3397           old_ident = silc_command_get_ident(cmd->payload);
3398           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3399           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3400           
3401           /* Send JOIN command to our router */
3402           silc_server_packet_send(server, (SilcSocketConnection)
3403                                   server->router->connection,
3404                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3405                                   tmpbuf->data, tmpbuf->len, TRUE);
3406           
3407           /* Reprocess this packet after received reply from router */
3408           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3409                                       silc_command_get_ident(cmd->payload),
3410                                       silc_server_command_join,
3411                                       silc_server_command_dup(cmd));
3412           cmd->pending = TRUE;
3413           silc_command_set_ident(cmd->payload, old_ident);
3414           silc_buffer_free(tmpbuf);
3415           goto out;
3416         }
3417         
3418         /* We are router and the channel does not seem exist so we will check
3419            our global list as well for the channel. */
3420         channel = silc_idlist_find_channel_by_name(server->global_list, 
3421                                                    channel_name, NULL);
3422         if (!channel) {
3423           /* Channel really does not exist, create it */
3424           channel = silc_server_create_new_channel(server, server->id, cipher, 
3425                                                    hmac, channel_name, TRUE);
3426           if (!channel) {
3427             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3428                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3429             goto out;
3430           }
3431
3432           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3433           created = TRUE;
3434           create_key = FALSE;
3435         }
3436       }
3437     }
3438   } else {
3439     if (!channel) {
3440       /* Channel not found */
3441
3442       /* If the command came from router and we are normal server then
3443          something went wrong with the joining as the channel was not found.
3444          We can't do anything else but ignore this. */
3445       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3446           server->server_type != SILC_ROUTER)
3447         goto out;
3448       
3449       /* We are router and the channel does not seem exist so we will check
3450          our global list as well for the channel. */
3451       channel = silc_idlist_find_channel_by_name(server->global_list, 
3452                                                  channel_name, NULL);
3453       if (!channel) {
3454         /* Channel really does not exist, create it */
3455         channel = silc_server_create_new_channel(server, server->id, cipher, 
3456                                                  hmac, channel_name, TRUE);
3457         if (!channel) {
3458           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3459                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3460           goto out;
3461         }
3462
3463         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3464         created = TRUE;
3465         create_key = FALSE;
3466       }
3467     }
3468   }
3469
3470   /* Check whether the channel was created by our router */
3471   if (cmd->pending && context2) {
3472     SilcServerCommandReplyContext reply = 
3473       (SilcServerCommandReplyContext)context2;
3474
3475     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3476       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3477       SILC_GET32_MSB(created, tmp);
3478       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3479         create_key = FALSE;     /* Router returned the key already */
3480     }
3481
3482     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3483         !silc_hash_table_count(channel->user_list))
3484       created = TRUE;
3485   }
3486
3487   /* If the channel does not have global users and is also empty the client
3488      will be the channel founder and operator. */
3489   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3490     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3491
3492   /* Join to the channel */
3493   silc_server_command_join_channel(server, cmd, channel, client_id,
3494                                    created, create_key, umode,
3495                                    auth, auth_len);
3496
3497   silc_free(client_id);
3498
3499  out:
3500   silc_server_command_free(cmd);
3501 }
3502
3503 /* Server side of command MOTD. Sends server's current "message of the
3504    day" to the client. */
3505
3506 SILC_SERVER_CMD_FUNC(motd)
3507 {
3508   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3509   SilcServer server = cmd->server;
3510   SilcBuffer packet, idp;
3511   char *motd, *dest_server;
3512   uint32 motd_len;
3513   uint16 ident = silc_command_get_ident(cmd->payload);
3514   
3515   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3516
3517   /* Get server name */
3518   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3519   if (!dest_server) {
3520     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3521                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3522     goto out;
3523   }
3524
3525   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3526     /* Send our MOTD */
3527
3528     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3529
3530     if (server->config && server->config->server_info &&
3531         server->config->server_info->motd_file) {
3532       /* Send motd */
3533       motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3534       if (!motd)
3535         goto out;
3536       
3537       motd[motd_len] = 0;
3538       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3539                                                     SILC_STATUS_OK, ident, 2,
3540                                                     2, idp, idp->len,
3541                                                     3, motd, motd_len);
3542     } else {
3543       /* No motd */
3544       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3545                                                     SILC_STATUS_OK, ident, 1,
3546                                                     2, idp, idp->len);
3547     }
3548
3549     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3550                             packet->data, packet->len, FALSE);
3551     silc_buffer_free(packet);
3552     silc_buffer_free(idp);
3553   } else {
3554     SilcServerEntry entry;
3555
3556     /* Check whether we have this server cached */
3557     entry = silc_idlist_find_server_by_name(server->global_list,
3558                                             dest_server, TRUE, NULL);
3559     if (!entry) {
3560       entry = silc_idlist_find_server_by_name(server->local_list,
3561                                               dest_server, TRUE, NULL);
3562     }
3563
3564     if (server->server_type != SILC_SERVER && !cmd->pending && 
3565         entry && !entry->motd) {
3566       /* Send to the server */
3567       SilcBuffer tmpbuf;
3568       uint16 old_ident;
3569
3570       old_ident = silc_command_get_ident(cmd->payload);
3571       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3572       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3573
3574       silc_server_packet_send(server, entry->connection,
3575                               SILC_PACKET_COMMAND, cmd->packet->flags,
3576                               tmpbuf->data, tmpbuf->len, TRUE);
3577
3578       /* Reprocess this packet after received reply from router */
3579       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3580                                   silc_command_get_ident(cmd->payload),
3581                                   silc_server_command_motd,
3582                                   silc_server_command_dup(cmd));
3583       cmd->pending = TRUE;
3584       silc_command_set_ident(cmd->payload, old_ident);
3585       silc_buffer_free(tmpbuf);
3586       goto out;
3587     }
3588
3589     if (!entry && !cmd->pending && !server->standalone) {
3590       /* Send to the primary router */
3591       SilcBuffer tmpbuf;
3592       uint16 old_ident;
3593
3594       old_ident = silc_command_get_ident(cmd->payload);
3595       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3596       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3597
3598       silc_server_packet_send(server, server->router->connection,
3599                               SILC_PACKET_COMMAND, cmd->packet->flags,
3600                               tmpbuf->data, tmpbuf->len, TRUE);
3601
3602       /* Reprocess this packet after received reply from router */
3603       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3604                                   silc_command_get_ident(cmd->payload),
3605                                   silc_server_command_motd,
3606                                   silc_server_command_dup(cmd));
3607       cmd->pending = TRUE;
3608       silc_command_set_ident(cmd->payload, old_ident);
3609       silc_buffer_free(tmpbuf);
3610       goto out;
3611     }
3612
3613     if (!entry) {
3614       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3615                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3616       goto out;
3617     }
3618
3619     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3620     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3621                                                   SILC_STATUS_OK, ident, 2,
3622                                                   2, idp, idp->len,
3623                                                   3, entry->motd,
3624                                                   entry->motd ? 
3625                                                   strlen(entry->motd) : 0);
3626     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3627                             packet->data, packet->len, FALSE);
3628     silc_buffer_free(packet);
3629     silc_buffer_free(idp);
3630   }
3631
3632  out:
3633   silc_server_command_free(cmd);
3634 }
3635
3636 /* Server side of command UMODE. Client can use this command to set/unset
3637    user mode. Client actually cannot set itself to be as server/router
3638    operator so this can be used only to unset the modes. */
3639
3640 SILC_SERVER_CMD_FUNC(umode)
3641 {
3642   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3643   SilcServer server = cmd->server;
3644   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3645   SilcBuffer packet;
3646   unsigned char *tmp_mask;
3647   uint32 mask;
3648   uint16 ident = silc_command_get_ident(cmd->payload);
3649
3650   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3651     goto out;
3652
3653   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3654
3655   /* Get the client's mode mask */
3656   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3657   if (!tmp_mask) {
3658     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3659                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3660     goto out;
3661   }
3662   SILC_GET32_MSB(mask, tmp_mask);
3663
3664   /* 
3665    * Change the mode 
3666    */
3667
3668   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3669     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3670       /* Cannot operator mode */
3671       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3672                                             SILC_STATUS_ERR_PERM_DENIED);
3673       goto out;
3674     }
3675   } else {
3676     /* Remove the server operator rights */
3677     if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3678       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3679       if (client->connection)
3680         server->stat.my_server_ops--;
3681       if (server->server_type == SILC_ROUTER)
3682         server->stat.server_ops--;
3683     }
3684   }
3685
3686   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3687     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3688       /* Cannot operator mode */
3689       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3690                                             SILC_STATUS_ERR_PERM_DENIED);
3691       goto out;
3692     }
3693   } else {
3694     /* Remove the router operator rights */
3695     if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3696       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3697       if (client->connection)
3698         server->stat.my_router_ops--;
3699       if (server->server_type == SILC_ROUTER)
3700         server->stat.router_ops--;
3701     }
3702   }
3703
3704   if (mask & SILC_UMODE_GONE) {
3705     client->mode |= SILC_UMODE_GONE;
3706   } else {
3707     if (client->mode & SILC_UMODE_GONE)
3708       /* Remove the gone status */
3709       client->mode &= ~SILC_UMODE_GONE;
3710   }
3711
3712   /* Send UMODE change to primary router */
3713   if (!server->standalone)
3714     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3715                                   client->id, client->mode);
3716
3717   /* Send command reply to sender */
3718   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3719                                                 SILC_STATUS_OK, ident, 1,
3720                                                 2, tmp_mask, 4);
3721   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3722                           packet->data, packet->len, FALSE);
3723   silc_buffer_free(packet);
3724
3725  out:
3726   silc_server_command_free(cmd);
3727 }
3728
3729 /* Checks that client has rights to add or remove channel modes. If any
3730    of the checks fails FALSE is returned. */
3731
3732 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3733                                    SilcChannelClientEntry client,
3734                                    uint32 mode)
3735 {
3736   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3737   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3738
3739   /* Check whether has rights to change anything */
3740   if (!is_op && !is_fo)
3741     return FALSE;
3742
3743   /* Check whether has rights to change everything */
3744   if (is_op && is_fo)
3745     return TRUE;
3746
3747   /* We know that client is channel operator, check that they are not
3748      changing anything that requires channel founder rights. Rest of the
3749      modes are available automatically for channel operator. */
3750
3751   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3752     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3753       if (is_op && !is_fo)
3754         return FALSE;
3755   } else {
3756     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3757       if (is_op && !is_fo)
3758         return FALSE;
3759     }
3760   }
3761   
3762   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3763     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3764       if (is_op && !is_fo)
3765         return FALSE;
3766   } else {
3767     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3768       if (is_op && !is_fo)
3769         return FALSE;
3770     }
3771   }
3772
3773   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3774     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3775       if (is_op && !is_fo)
3776         return FALSE;
3777   } else {
3778     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3779       if (is_op && !is_fo)
3780         return FALSE;
3781     }
3782   }
3783   
3784   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3785     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3786       if (is_op && !is_fo)
3787         return FALSE;
3788   } else {
3789     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3790       if (is_op && !is_fo)
3791         return FALSE;
3792     }
3793   }
3794   
3795   return TRUE;
3796 }
3797
3798 /* Server side command of CMODE. Changes channel mode */
3799
3800 SILC_SERVER_CMD_FUNC(cmode)
3801 {
3802   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3803   SilcServer server = cmd->server;
3804   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3805   SilcIDListData idata = (SilcIDListData)client;
3806   SilcChannelID *channel_id;
3807   SilcChannelEntry channel;
3808   SilcChannelClientEntry chl;
3809   SilcBuffer packet, cidp;
3810   unsigned char *tmp, *tmp_id, *tmp_mask;
3811   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3812   uint32 mode_mask, tmp_len, tmp_len2;
3813   uint16 ident = silc_command_get_ident(cmd->payload);
3814
3815   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3816
3817   /* Get Channel ID */
3818   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3819   if (!tmp_id) {
3820     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3821                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3822     goto out;
3823   }
3824   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3825   if (!channel_id) {
3826     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3828     goto out;
3829   }
3830
3831   /* Get the channel mode mask */
3832   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3833   if (!tmp_mask) {
3834     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3835                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3836     goto out;
3837   }
3838   SILC_GET32_MSB(mode_mask, tmp_mask);
3839
3840   /* Get channel entry */
3841   channel = silc_idlist_find_channel_by_id(server->local_list, 
3842                                            channel_id, NULL);
3843   if (!channel) {
3844     channel = silc_idlist_find_channel_by_id(server->global_list, 
3845                                              channel_id, NULL);
3846     if (!channel) {
3847       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3848                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3849       goto out;
3850     }
3851   }
3852
3853   /* Check whether this client is on the channel */
3854   if (!silc_server_client_on_channel(client, channel)) {
3855     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3856                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3857     goto out;
3858   }
3859
3860   /* Get entry to the channel user list */
3861   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3862
3863   /* Check that client has rights to change any requested channel modes */
3864   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3865     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3866                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3867     goto out;
3868   }
3869
3870   /*
3871    * Check the modes. Modes that requires nothing special operation are
3872    * not checked here.
3873    */
3874
3875   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3876     /* Channel uses private keys to protect traffic. Client(s) has set the
3877        key locally they want to use, server does not know that key. */
3878     /* Nothing interesting to do here */
3879   } else {
3880     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3881       /* The mode is removed and we need to generate and distribute
3882          new channel key. Clients are not using private channel keys
3883          anymore after this. */
3884       
3885       /* Re-generate channel key */
3886       if (!silc_server_create_channel_key(server, channel, 0))
3887         goto out;
3888         
3889       /* Send the channel key. This sends it to our local clients and if
3890          we are normal server to our router as well. */
3891       silc_server_send_channel_key(server, NULL, channel, 
3892                                    server->server_type == SILC_ROUTER ? 
3893                                    FALSE : !server->standalone);
3894         
3895       cipher = channel->channel_key->cipher->name;
3896       hmac = (char *)silc_hmac_get_name(channel->hmac);
3897     }
3898   }
3899
3900   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3901     /* User limit is set on channel */
3902     uint32 user_limit;
3903       
3904     /* Get user limit */
3905     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3906     if (!tmp) {
3907       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3908         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3910         goto out;
3911       }
3912     } else {
3913       SILC_GET32_MSB(user_limit, tmp);
3914       channel->user_limit = user_limit;
3915     }
3916   } else {
3917     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3918       /* User limit mode is unset. Remove user limit */
3919       channel->user_limit = 0;
3920   }
3921
3922   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3923     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3924       /* Passphrase has been set to channel */
3925       
3926       /* Get the passphrase */
3927       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3928       if (!tmp) {
3929         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3930                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3931         goto out;
3932       }
3933
3934       /* Save the passphrase */
3935       passphrase = channel->passphrase = strdup(tmp);
3936     }
3937   } else {
3938     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3939       /* Passphrase mode is unset. remove the passphrase */
3940       if (channel->passphrase) {
3941         silc_free(channel->passphrase);
3942         channel->passphrase = NULL;
3943       }
3944     }
3945   }
3946
3947   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3948     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3949       /* Cipher to use protect the traffic */
3950       SilcCipher newkey, oldkey;
3951
3952       /* Get cipher */
3953       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3954       if (!cipher) {
3955         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3956                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3957         goto out;
3958       }
3959
3960       /* Delete old cipher and allocate the new one */
3961       if (!silc_cipher_alloc(cipher, &newkey)) {
3962         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3964         goto out;
3965       }
3966
3967       oldkey = channel->channel_key;
3968       channel->channel_key = newkey;
3969
3970       /* Re-generate channel key */
3971       if (!silc_server_create_channel_key(server, channel, 0)) {
3972         /* We don't have new key, revert to old one */
3973         channel->channel_key = oldkey;
3974         goto out;
3975       }
3976
3977       /* Remove old channel key for good */
3978       silc_cipher_free(oldkey);
3979
3980       /* Send the channel key. This sends it to our local clients and if
3981          we are normal server to our router as well. */
3982       silc_server_send_channel_key(server, NULL, channel, 
3983                                    server->server_type == SILC_ROUTER ? 
3984                                    FALSE : !server->standalone);
3985     }
3986   } else {
3987     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3988       /* Cipher mode is unset. Remove the cipher and revert back to 
3989          default cipher */
3990       SilcCipher newkey, oldkey;
3991       cipher = channel->cipher;
3992
3993       /* Delete old cipher and allocate default one */
3994       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3995         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3996                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3997         goto out;
3998       }
3999
4000       oldkey = channel->channel_key;
4001       channel->channel_key = newkey;
4002
4003       /* Re-generate channel key */
4004       if (!silc_server_create_channel_key(server, channel, 0)) {
4005         /* We don't have new key, revert to old one */
4006         channel->channel_key = oldkey;
4007         goto out;
4008       }
4009       
4010       /* Remove old channel key for good */
4011       silc_cipher_free(oldkey);
4012
4013       /* Send the channel key. This sends it to our local clients and if
4014          we are normal server to our router as well. */
4015       silc_server_send_channel_key(server, NULL, channel, 
4016                                    server->server_type == SILC_ROUTER ? 
4017                                    FALSE : !server->standalone);
4018     }
4019   }
4020
4021   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4022     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4023       /* HMAC to use protect the traffic */
4024       unsigned char hash[32];
4025       SilcHmac newhmac;
4026
4027       /* Get hmac */
4028       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4029       if (!hmac) {
4030         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4031                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4032         goto out;
4033       }
4034
4035       /* Delete old hmac and allocate the new one */
4036       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4037         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4038                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4039         goto out;
4040       }
4041
4042       silc_hmac_free(channel->hmac);
4043       channel->hmac = newhmac;
4044
4045       /* Set the HMAC key out of current channel key. The client must do
4046          this locally. */
4047       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4048                      channel->key_len / 8, hash);
4049       silc_hmac_set_key(channel->hmac, hash, 
4050                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4051       memset(hash, 0, sizeof(hash));
4052     }
4053   } else {
4054     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4055       /* Hmac mode is unset. Remove the hmac and revert back to 
4056          default hmac */
4057       SilcHmac newhmac;
4058       unsigned char hash[32];
4059       hmac = channel->hmac_name;
4060
4061       /* Delete old hmac and allocate default one */
4062       silc_hmac_free(channel->hmac);
4063       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4064         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4065                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4066         goto out;
4067       }
4068
4069       silc_hmac_free(channel->hmac);
4070       channel->hmac = newhmac;
4071
4072       /* Set the HMAC key out of current channel key. The client must do
4073          this locally. */
4074       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4075                      channel->key_len / 8, 
4076                      hash);
4077       silc_hmac_set_key(channel->hmac, hash, 
4078                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4079       memset(hash, 0, sizeof(hash));
4080     }
4081   }
4082
4083   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4084     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4085       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4086         /* Set the founder authentication */
4087         SilcAuthPayload auth;
4088         
4089         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4090         if (!tmp) {
4091           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4092                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4093           goto out;
4094         }
4095
4096         auth = silc_auth_payload_parse(tmp, tmp_len);
4097         if (!auth) {
4098           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4099                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4100           goto out;
4101         }
4102
4103         /* Save the public key */
4104         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4105         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4106         silc_free(tmp);
4107         
4108         channel->founder_method = silc_auth_get_method(auth);
4109
4110         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4111           tmp = silc_auth_get_data(auth, &tmp_len);
4112           channel->founder_passwd = 
4113             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4114           memcpy(channel->founder_passwd, tmp, tmp_len);
4115           channel->founder_passwd_len = tmp_len;
4116         } else {
4117           /* Verify the payload before setting the mode */
4118           if (!silc_auth_verify(auth, channel->founder_method, 
4119                                 channel->founder_key, 0, idata->hash,
4120                                 client->id, SILC_ID_CLIENT)) {
4121             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4122                                                   SILC_STATUS_ERR_AUTH_FAILED);
4123             goto out;
4124           }
4125         }
4126
4127         silc_auth_payload_free(auth);
4128       }
4129     }
4130   } else {
4131     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4132       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4133         if (channel->founder_key)
4134           silc_pkcs_public_key_free(channel->founder_key);
4135         if (channel->founder_passwd) {
4136           silc_free(channel->founder_passwd);
4137           channel->founder_passwd = NULL;
4138         }
4139       }
4140     }
4141   }
4142
4143   /* Finally, set the mode */
4144   channel->mode = mode_mask;
4145
4146   /* Send CMODE_CHANGE notify. */
4147   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4148   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4149                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4150                                      cidp->data, cidp->len, 
4151                                      tmp_mask, 4,
4152                                      cipher, cipher ? strlen(cipher) : 0,
4153                                      hmac, hmac ? strlen(hmac) : 0,
4154                                      passphrase, passphrase ? 
4155                                      strlen(passphrase) : 0);
4156
4157   /* Set CMODE notify type to network */
4158   if (!server->standalone)
4159     silc_server_send_notify_cmode(server, server->router->connection,
4160                                   server->server_type == SILC_ROUTER ? 
4161                                   TRUE : FALSE, channel,
4162                                   mode_mask, client->id, SILC_ID_CLIENT,
4163                                   cipher, hmac, passphrase);
4164
4165   /* Send command reply to sender */
4166   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4167                                                 SILC_STATUS_OK, ident, 2,
4168                                                 2, tmp_id, tmp_len2,
4169                                                 3, tmp_mask, 4);
4170   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4171                           packet->data, packet->len, FALSE);
4172     
4173   silc_buffer_free(packet);
4174   silc_free(channel_id);
4175   silc_buffer_free(cidp);
4176
4177  out:
4178   silc_server_command_free(cmd);
4179 }
4180
4181 /* Server side of CUMODE command. Changes client's mode on a channel. */
4182
4183 SILC_SERVER_CMD_FUNC(cumode)
4184 {
4185   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4186   SilcServer server = cmd->server;
4187   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4188   SilcIDListData idata = (SilcIDListData)client;
4189   SilcChannelID *channel_id;
4190   SilcClientID *client_id;
4191   SilcChannelEntry channel;
4192   SilcClientEntry target_client;
4193   SilcChannelClientEntry chl;
4194   SilcBuffer packet, idp;
4195   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4196   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4197   int notify = FALSE;
4198   uint16 ident = silc_command_get_ident(cmd->payload);
4199
4200   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4201
4202   /* Get Channel ID */
4203   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4204   if (!tmp_ch_id) {
4205     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4207     goto out;
4208   }
4209   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4210   if (!channel_id) {
4211     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4213     goto out;
4214   }
4215
4216   /* Get channel entry */
4217   channel = silc_idlist_find_channel_by_id(server->local_list, 
4218                                            channel_id, NULL);
4219   if (!channel) {
4220     channel = silc_idlist_find_channel_by_id(server->global_list, 
4221                                              channel_id, NULL);
4222     if (!channel) {
4223       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4225       goto out;
4226     }
4227   }
4228
4229   /* Check whether sender is on the channel */
4230   if (!silc_server_client_on_channel(client, channel)) {
4231     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4233     goto out;
4234   }
4235
4236   /* Check that client has rights to change other's rights */
4237   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4238   sender_mask = chl->mode;
4239   
4240   /* Get the target client's channel mode mask */
4241   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4242   if (!tmp_mask) {
4243     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4245     goto out;
4246   }
4247   SILC_GET32_MSB(target_mask, tmp_mask);
4248
4249   /* Get target Client ID */
4250   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4251   if (!tmp_id) {
4252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4254     goto out;
4255   }
4256   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4257   if (!client_id) {
4258     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4259                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4260     goto out;
4261   }
4262
4263   /* Get target client's entry */
4264   target_client = silc_idlist_find_client_by_id(server->local_list, 
4265                                                 client_id, TRUE, NULL);
4266   if (!target_client) {
4267     target_client = silc_idlist_find_client_by_id(server->global_list, 
4268                                                   client_id, TRUE, NULL);
4269   }
4270
4271   if (target_client != client &&
4272       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4273       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4274     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4275                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4276     goto out;
4277   }
4278
4279   /* Check whether target client is on the channel */
4280   if (target_client != client) {
4281     if (!silc_server_client_on_channel(target_client, channel)) {
4282       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4283                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4284       goto out;
4285     }
4286
4287     /* Get entry to the channel user list */
4288     silc_hash_table_find(channel->user_list, target_client, NULL, 
4289                          (void *)&chl);
4290   }
4291
4292   /* 
4293    * Change the mode 
4294    */
4295
4296   /* If the target client is founder, no one else can change their mode
4297      but themselves. */
4298   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4299     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4300                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4301     goto out;
4302   }
4303
4304   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4305     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4306       /* The client tries to claim the founder rights. */
4307       unsigned char *tmp_auth;
4308       uint32 tmp_auth_len, auth_len;
4309       void *auth;
4310       
4311       if (target_client != client) {
4312         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4313                                               SILC_STATUS_ERR_NOT_YOU);
4314         goto out;
4315       }
4316
4317       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4318           !channel->founder_key || !idata->public_key ||
4319           !silc_pkcs_public_key_compare(channel->founder_key, 
4320                                         idata->public_key)) {
4321         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322                                               SILC_STATUS_ERR_NOT_YOU);
4323         goto out;
4324       }
4325
4326       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4327       if (!tmp_auth) {
4328         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4329                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4330         goto out;
4331       }
4332
4333       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4334               (void *)channel->founder_passwd : (void *)channel->founder_key);
4335       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4336                   channel->founder_passwd_len : 0);
4337       
4338       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4339                                  channel->founder_method, auth, auth_len,
4340                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4341         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4342                                               SILC_STATUS_ERR_AUTH_FAILED);
4343         goto out;
4344       }
4345       
4346       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4347       notify = TRUE;
4348     }
4349   } else {
4350     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4351       if (target_client == client) {
4352         /* Remove channel founder rights from itself */
4353         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4354         notify = TRUE;
4355       } else {
4356         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4357                                               SILC_STATUS_ERR_NOT_YOU);
4358         goto out;
4359       }
4360     }
4361   }
4362
4363   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4364     /* Promote to operator */
4365     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4366       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4367           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4368         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4369                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4370         goto out;
4371       }
4372
4373       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4374       notify = TRUE;
4375     }
4376   } else {
4377     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4378       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4379           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4380         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4381                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4382         goto out;
4383       }
4384
4385       /* Demote to normal user */
4386       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4387       notify = TRUE;
4388     }
4389   }
4390
4391   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4392   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4393
4394   /* Send notify to channel, notify only if mode was actually changed. */
4395   if (notify) {
4396     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4397                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4398                                        idp->data, idp->len,
4399                                        tmp_mask, 4, 
4400                                        tmp_id, tmp_len);
4401
4402     /* Set CUMODE notify type to network */
4403     if (!server->standalone)
4404       silc_server_send_notify_cumode(server, server->router->connection,
4405                                      server->server_type == SILC_ROUTER ? 
4406                                      TRUE : FALSE, channel,
4407                                      target_mask, client->id, 
4408                                      SILC_ID_CLIENT,
4409                                      target_client->id);
4410   }
4411
4412   /* Send command reply to sender */
4413   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4414                                                 SILC_STATUS_OK, ident, 3,
4415                                                 2, tmp_mask, 4,
4416                                                 3, tmp_ch_id, tmp_ch_len,
4417                                                 4, tmp_id, tmp_len);
4418   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4419                           packet->data, packet->len, FALSE);
4420     
4421   silc_buffer_free(packet);
4422   silc_free(channel_id);
4423   silc_free(client_id);
4424   silc_buffer_free(idp);
4425
4426  out:
4427   silc_server_command_free(cmd);
4428 }
4429
4430 /* Server side of KICK command. Kicks client out of channel. */
4431
4432 SILC_SERVER_CMD_FUNC(kick)
4433 {
4434   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4435   SilcServer server = cmd->server;
4436   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4437   SilcClientEntry target_client;
4438   SilcChannelID *channel_id;
4439   SilcClientID *client_id;
4440   SilcChannelEntry channel;
4441   SilcChannelClientEntry chl;
4442   SilcBuffer idp;
4443   uint32 tmp_len, target_idp_len;
4444   unsigned char *tmp, *comment, *target_idp;
4445
4446   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4447
4448   /* Get Channel ID */
4449   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4450   if (!tmp) {
4451     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4452                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4453     goto out;
4454   }
4455   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4456   if (!channel_id) {
4457     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4458                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4459     goto out;
4460   }
4461
4462   /* Get channel entry */
4463   channel = silc_idlist_find_channel_by_id(server->local_list, 
4464                                            channel_id, NULL);
4465   if (!channel) {
4466     channel = silc_idlist_find_channel_by_id(server->local_list, 
4467                                              channel_id, NULL);
4468     if (!channel) {
4469       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4470                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4471       goto out;
4472     }
4473   }
4474
4475   /* Check whether sender is on the channel */
4476   if (!silc_server_client_on_channel(client, channel)) {
4477     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4478                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4479     goto out;
4480   }
4481
4482   /* Check that the kicker is channel operator or channel founder */
4483   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4484   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4485     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4486                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4487     goto out;
4488   }
4489   
4490   /* Get target Client ID */
4491   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4492   if (!target_idp) {
4493     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4494                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4495     goto out;
4496   }
4497   client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4498   if (!client_id) {
4499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4501     goto out;
4502   }
4503
4504   /* Get target client's entry */
4505   target_client = silc_idlist_find_client_by_id(server->local_list, 
4506                                                 client_id, TRUE, NULL);
4507   if (!target_client) {
4508     target_client = silc_idlist_find_client_by_id(server->global_list, 
4509                                                   client_id, TRUE, NULL);
4510   }
4511
4512   /* Check that the target client is not channel founder. Channel founder
4513      cannot be kicked from the channel. */
4514   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4515   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4516     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4517                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4518     goto out;
4519   }
4520   
4521   /* Check whether target client is on the channel */
4522   if (!silc_server_client_on_channel(target_client, channel)) {
4523     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4524                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4525     goto out;
4526   }
4527
4528   /* Get comment */
4529   tmp_len = 0;
4530   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4531   if (tmp_len > 128)
4532     comment = NULL;
4533
4534   /* Send command reply to sender */
4535   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4536                                         SILC_STATUS_OK);
4537
4538   /* Send KICKED notify to local clients on the channel */
4539   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4540   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4541                                      SILC_NOTIFY_TYPE_KICKED, 3,
4542                                      target_idp, target_idp_len,
4543                                      comment, comment ? strlen(comment) : 0,
4544                                      idp->data, idp->len);
4545   silc_buffer_free(idp);
4546
4547   /* Remove the client from the channel. If the channel does not exist
4548      after removing the client then the client kicked itself off the channel
4549      and we don't have to send anything after that. */
4550   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4551                                            target_client, FALSE))
4552     goto out;
4553
4554   /* Send KICKED notify to primary route */
4555   if (!server->standalone)
4556     silc_server_send_notify_kicked(server, server->router->connection,
4557                                    server->server_type == SILC_ROUTER ?
4558                                    TRUE : FALSE, channel,
4559                                    target_client->id, client->id, comment);
4560
4561   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4562     /* Re-generate channel key */
4563     if (!silc_server_create_channel_key(server, channel, 0))
4564       goto out;
4565     
4566     /* Send the channel key to the channel. The key of course is not sent
4567        to the client who was kicked off the channel. */
4568     silc_server_send_channel_key(server, target_client->connection, channel, 
4569                                  server->server_type == SILC_ROUTER ? 
4570                                  FALSE : !server->standalone);
4571   }
4572
4573  out:
4574   silc_server_command_free(cmd);
4575 }
4576
4577 /* Server side of OPER command. Client uses this comand to obtain server
4578    operator privileges to this server/router. */
4579
4580 SILC_SERVER_CMD_FUNC(oper)
4581 {
4582   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4583   SilcServer server = cmd->server;
4584   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4585   unsigned char *username, *auth;
4586   uint32 tmp_len;
4587   SilcServerConfigAdmin *admin;
4588   SilcIDListData idata = (SilcIDListData)client;
4589   bool result = FALSE;
4590
4591   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4592
4593   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4594     goto out;
4595
4596   /* Get the username */
4597   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4598   if (!username) {
4599     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4600                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4601     goto out;
4602   }
4603
4604   /* Get the admin configuration */
4605   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4606                                         username, client->nickname);
4607   if (!admin) {
4608     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4609                                           username, client->nickname);
4610     if (!admin) {
4611       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4612                                             SILC_STATUS_ERR_AUTH_FAILED);
4613       goto out;
4614     }
4615   }
4616
4617   /* Get the authentication payload */
4618   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4619   if (!auth) {
4620     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4621                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4622     goto out;
4623   }
4624
4625   /* Verify the authentication data. If both passphrase and public key
4626      is set then try both of them. */
4627   if (admin->passphrase)
4628     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4629                                    admin->passphrase, admin->passphrase_len,
4630                                    idata->hash, client->id, SILC_ID_CLIENT);
4631   if (!result && admin->publickey)
4632     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4633                                    admin->publickey, 0,
4634                                    idata->hash, client->id, SILC_ID_CLIENT);
4635   if (!result) {
4636     /* Authentication failed */
4637     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4638                                           SILC_STATUS_ERR_AUTH_FAILED);
4639     goto out;
4640   }
4641
4642   /* Client is now server operator */
4643   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4644
4645   /* Update statistics */
4646   if (client->connection)
4647     server->stat.my_server_ops++;
4648   if (server->server_type == SILC_ROUTER)
4649     server->stat.server_ops++;
4650
4651   /* Send UMODE change to primary router */
4652   if (!server->standalone)
4653     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4654                                   client->id, client->mode);
4655
4656   /* Send reply to the sender */
4657   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4658                                         SILC_STATUS_OK);
4659
4660  out:
4661   silc_server_command_free(cmd);
4662 }
4663
4664 /* Server side of SILCOPER command. Client uses this comand to obtain router
4665    operator privileges to this router. */
4666
4667 SILC_SERVER_CMD_FUNC(silcoper)
4668 {
4669   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4670   SilcServer server = cmd->server;
4671   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4672   unsigned char *username, *auth;
4673   uint32 tmp_len;
4674   SilcServerConfigAdmin *admin;
4675   SilcIDListData idata = (SilcIDListData)client;
4676   bool result = FALSE;
4677
4678   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4679
4680   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4681     goto out;
4682
4683   if (server->server_type != SILC_ROUTER) {
4684     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4685                                           SILC_STATUS_ERR_AUTH_FAILED);
4686     goto out;
4687   }
4688
4689   /* Get the username */
4690   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4691   if (!username) {
4692     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4693                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4694     goto out;
4695   }
4696
4697   /* Get the admin configuration */
4698   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4699                                         username, client->nickname);
4700   if (!admin) {
4701     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4702                                           username, client->nickname);
4703     if (!admin) {
4704       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4705                                             SILC_STATUS_ERR_AUTH_FAILED);
4706       goto out;
4707     }
4708   }
4709
4710   /* Get the authentication payload */
4711   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4712   if (!auth) {
4713     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4714                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4715     goto out;
4716   }
4717
4718   /* Verify the authentication data. If both passphrase and public key
4719      is set then try both of them. */
4720   if (admin->passphrase)
4721     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4722                                    admin->passphrase, admin->passphrase_len,
4723                                    idata->hash, client->id, SILC_ID_CLIENT);
4724   if (!result && admin->publickey)
4725     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4726                                    admin->publickey, 0,
4727                                    idata->hash, client->id, SILC_ID_CLIENT);
4728   if (!result) {
4729     /* Authentication failed */
4730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4731                                           SILC_STATUS_ERR_AUTH_FAILED);
4732     goto out;
4733   }
4734
4735   /* Client is now router operator */
4736   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4737
4738   /* Update statistics */
4739   if (client->connection)
4740     server->stat.my_router_ops++;
4741   if (server->server_type == SILC_ROUTER)
4742     server->stat.router_ops++;
4743
4744   /* Send UMODE change to primary router */
4745   if (!server->standalone)
4746     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4747                                   client->id, client->mode);
4748
4749   /* Send reply to the sender */
4750   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4751                                         SILC_STATUS_OK);
4752
4753  out:
4754   silc_server_command_free(cmd);
4755 }
4756
4757 /* Server side command of CONNECT. Connects us to the specified remote
4758    server or router. */
4759
4760 SILC_SERVER_CMD_FUNC(connect)
4761 {
4762   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4763   SilcServer server = cmd->server;
4764   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4765   unsigned char *tmp, *host;
4766   uint32 tmp_len;
4767   uint32 port = SILC_PORT;
4768
4769   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4770
4771   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4772     goto out;
4773
4774   /* Check whether client has the permissions. */
4775   if (client->mode == SILC_UMODE_NONE) {
4776     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4777                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4778     goto out;
4779   }
4780
4781   if (server->server_type == SILC_ROUTER && 
4782       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4784                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4785     goto out;
4786   }
4787
4788   /* Get the remote server */
4789   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4790   if (!host) {
4791     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4792                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4793     goto out;
4794   }
4795
4796   /* Get port */
4797   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4798   if (tmp)
4799     SILC_GET32_MSB(port, tmp);
4800
4801   /* Create the connection. It is done with timeout and is async. */
4802   silc_server_create_connection(server, host, port);
4803
4804   /* Send reply to the sender */
4805   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4806                                         SILC_STATUS_OK);
4807
4808  out:
4809   silc_server_command_free(cmd);
4810 }
4811
4812 /* Server side of command BAN. This is used to manage the ban list of the
4813    channel. To add clients and remove clients from the ban list. */
4814
4815 SILC_SERVER_CMD_FUNC(ban)
4816 {
4817   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4818   SilcServer server = cmd->server;
4819   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4820   SilcBuffer packet;
4821   SilcChannelEntry channel;
4822   SilcChannelClientEntry chl;
4823   SilcChannelID *channel_id = NULL;
4824   unsigned char *id, *add, *del;
4825   uint32 id_len, tmp_len;
4826   uint16 ident = silc_command_get_ident(cmd->payload);
4827
4828   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4829     goto out;
4830
4831   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4832
4833   /* Get Channel ID */
4834   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4835   if (id) {
4836     channel_id = silc_id_payload_parse_id(id, id_len);
4837     if (!channel_id) {
4838       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4839                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4840       goto out;
4841     }
4842   }
4843
4844   /* Get channel entry. The server must know about the channel since the
4845      client is expected to be on the channel. */
4846   channel = silc_idlist_find_channel_by_id(server->local_list, 
4847                                            channel_id, NULL);
4848   if (!channel) {
4849     channel = silc_idlist_find_channel_by_id(server->global_list, 
4850                                              channel_id, NULL);
4851     if (!channel) {
4852       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4853                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4854       goto out;
4855     }
4856   }
4857
4858   /* Check whether this client is on the channel */
4859   if (!silc_server_client_on_channel(client, channel)) {
4860     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4861                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4862     goto out;
4863   }
4864
4865   /* Get entry to the channel user list */
4866   if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4867     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4868                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4869     goto out;
4870   }
4871
4872   /* The client must be at least channel operator. */
4873   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4875                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4876     goto out;
4877   }
4878
4879   /* Get the new ban and add it to the ban list */
4880   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4881   if (add) {
4882     if (!channel->ban_list)
4883       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4884     else
4885       channel->ban_list = silc_realloc(channel->ban_list, 
4886                                        sizeof(*channel->ban_list) * 
4887                                        (tmp_len + 
4888                                         strlen(channel->ban_list) + 2));
4889     if (add[tmp_len - 1] == ',')
4890       add[tmp_len - 1] = '\0';
4891
4892     strncat(channel->ban_list, add, tmp_len);
4893     strncat(channel->ban_list, ",", 1);
4894   }
4895
4896   /* Get the ban to be removed and remove it from the list */
4897   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4898   if (del && channel->ban_list) {
4899     char *start, *end, *n;
4900
4901     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4902       silc_free(channel->ban_list);
4903       channel->ban_list = NULL;
4904     } else {
4905       start = strstr(channel->ban_list, del);
4906       if (start && strlen(start) >= tmp_len) {
4907         end = start + tmp_len;
4908         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4909         strncat(n, channel->ban_list, start - channel->ban_list);
4910         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4911                              end) - 1);
4912         silc_free(channel->ban_list);
4913         channel->ban_list = n;
4914       }
4915     }
4916   }
4917
4918   /* Send the BAN notify type to our primary router. */
4919   if (!server->standalone && (add || del))
4920     silc_server_send_notify_ban(server, server->router->connection,
4921                                 server->server_type == SILC_ROUTER ?
4922                                 TRUE : FALSE, channel, add, del);
4923
4924   /* Send the reply back to the client */
4925   packet = 
4926     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4927                                          SILC_STATUS_OK, ident, 2,
4928                                          2, id, id_len,
4929                                          3, channel->ban_list, 
4930                                          channel->ban_list ? 
4931                                          strlen(channel->ban_list) -1 : 0);
4932   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4933                           packet->data, packet->len, FALSE);
4934     
4935   silc_buffer_free(packet);
4936
4937  out:
4938   silc_free(channel_id);
4939   silc_server_command_free(cmd);
4940 }
4941
4942 /* Server side command of CLOSE. Closes connection to a specified server. */
4943  
4944 SILC_SERVER_CMD_FUNC(close)
4945 {
4946   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4947   SilcServer server = cmd->server;
4948   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4949   SilcServerEntry server_entry;
4950   SilcSocketConnection sock;
4951   unsigned char *tmp;
4952   uint32 tmp_len;
4953   unsigned char *name;
4954   uint32 port = SILC_PORT;
4955
4956   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4957
4958   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4959     goto out;
4960
4961   /* Check whether client has the permissions. */
4962   if (client->mode == SILC_UMODE_NONE) {
4963     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4964                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4965     goto out;
4966   }
4967
4968   /* Get the remote server */
4969   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4970   if (!name) {
4971     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4972                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4973     goto out;
4974   }
4975
4976   /* Get port */
4977   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4978   if (tmp)
4979     SILC_GET32_MSB(port, tmp);
4980
4981   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4982                                                  name, port, FALSE, NULL);
4983   if (!server_entry)
4984     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4985                                                    name, port, FALSE, NULL);
4986   if (!server_entry) {
4987     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4988                                           SILC_STATUS_ERR_NO_SERVER_ID);
4989     goto out;
4990   }
4991
4992   /* Send reply to the sender */
4993   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4994                                         SILC_STATUS_OK);
4995
4996   /* Close the connection to the server */
4997   sock = (SilcSocketConnection)server_entry->connection;
4998
4999   /* If we shutdown primary router connection manually then don't trigger
5000      any reconnect or backup router connections, by setting the router
5001      to NULL here. */
5002   if (server->router == server_entry) {
5003     server->id_entry->router = NULL;
5004     server->router = NULL;
5005     server->standalone = TRUE;
5006   }
5007   silc_server_free_sock_user_data(server, sock, NULL);
5008   silc_server_close_connection(server, sock);
5009   
5010  out:
5011   silc_server_command_free(cmd);
5012 }
5013
5014 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5015    active connections. */
5016  
5017 SILC_SERVER_CMD_FUNC(shutdown)
5018 {
5019   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5020   SilcServer server = cmd->server;
5021   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5022
5023   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5024
5025   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5026     goto out;
5027
5028   /* Check whether client has the permission. */
5029   if (client->mode == SILC_UMODE_NONE) {
5030     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5031                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5032     goto out;
5033   }
5034
5035   /* Send reply to the sender */
5036   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5037                                         SILC_STATUS_OK);
5038
5039   /* Then, gracefully, or not, bring the server down. */
5040   silc_server_stop(server);
5041   exit(0);
5042
5043  out:
5044   silc_server_command_free(cmd);
5045 }
5046  
5047 /* Server side command of LEAVE. Removes client from a channel. */
5048
5049 SILC_SERVER_CMD_FUNC(leave)
5050 {
5051   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5052   SilcServer server = cmd->server;
5053   SilcSocketConnection sock = cmd->sock;
5054   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5055   SilcChannelID *id = NULL;
5056   SilcChannelEntry channel;
5057   uint32 len;
5058   unsigned char *tmp;
5059
5060   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5061
5062   /* Get Channel ID */
5063   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5064   if (!tmp) {
5065     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5066                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5067     goto out;
5068   }
5069   id = silc_id_payload_parse_id(tmp, len);
5070   if (!id) {
5071     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5072                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5073     goto out;
5074   }
5075
5076   /* Get channel entry */
5077   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5078   if (!channel) {
5079     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5080     if (!channel) {
5081       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5082                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5083       goto out;
5084     }
5085   }
5086
5087   /* Check whether this client is on the channel */
5088   if (!silc_server_client_on_channel(id_entry, channel)) {
5089     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5090                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
5091     goto out;
5092   }
5093
5094   /* Notify routers that they should remove this client from their list
5095      of clients on the channel. Send LEAVE notify type. */
5096   if (!server->standalone)
5097     silc_server_send_notify_leave(server, server->router->connection,
5098                                   server->server_type == SILC_ROUTER ?
5099                                   TRUE : FALSE, channel, id_entry->id);
5100
5101   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5102                                         SILC_STATUS_OK);
5103
5104   /* Remove client from channel */
5105   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5106                                            TRUE))
5107     /* If the channel does not exist anymore we won't send anything */
5108     goto out;
5109
5110   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5111     /* Re-generate channel key */
5112     if (!silc_server_create_channel_key(server, channel, 0))
5113       goto out;
5114
5115     /* Send the channel key */
5116     silc_server_send_channel_key(server, NULL, channel, 
5117                                  server->server_type == SILC_ROUTER ? 
5118                                  FALSE : !server->standalone);
5119   }
5120
5121  out:
5122   silc_free(id);
5123   silc_server_command_free(cmd);
5124 }
5125
5126 /* Server side of command USERS. Resolves clients and their USERS currently
5127    joined on the requested channel. The list of Client ID's and their modes
5128    on the channel is sent back. */
5129
5130 SILC_SERVER_CMD_FUNC(users)
5131 {
5132   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5133   SilcServer server = cmd->server;
5134   SilcChannelEntry channel;
5135   SilcChannelID *id = NULL;
5136   SilcBuffer packet, idp;
5137   unsigned char *channel_id;
5138   uint32 channel_id_len;
5139   SilcBuffer client_id_list;
5140   SilcBuffer client_mode_list;
5141   unsigned char lc[4];
5142   uint32 list_count = 0;
5143   uint16 ident = silc_command_get_ident(cmd->payload);
5144   char *channel_name;
5145
5146   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5147
5148   /* Get Channel ID */
5149   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5150
5151   /* Get channel name */
5152   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5153
5154   if (!channel_id && !channel_name) {
5155     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5156                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5157     goto out;
5158   }
5159
5160   if (channel_id) {
5161     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5162     if (!id) {
5163       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5164                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5165       goto out;
5166     }
5167   }
5168
5169   /* If we are server and we don't know about this channel we will send
5170      the command to our router. If we know about the channel then we also
5171      have the list of users already. */
5172   if (id)
5173     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5174   else
5175     channel = silc_idlist_find_channel_by_name(server->local_list, 
5176                                                channel_name, NULL);
5177
5178   if (!channel || channel->disabled) {
5179     if (server->server_type != SILC_ROUTER && !server->standalone &&
5180         !cmd->pending) {
5181       SilcBuffer tmpbuf;
5182       
5183       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5184       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5185       
5186       /* Send USERS command */
5187       silc_server_packet_send(server, server->router->connection,
5188                               SILC_PACKET_COMMAND, cmd->packet->flags,
5189                               tmpbuf->data, tmpbuf->len, TRUE);
5190       
5191       /* Reprocess this packet after received reply */
5192       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5193                                   silc_command_get_ident(cmd->payload),
5194                                   silc_server_command_users,
5195                                   silc_server_command_dup(cmd));
5196       cmd->pending = TRUE;
5197       silc_command_set_ident(cmd->payload, ident);
5198       silc_buffer_free(tmpbuf);
5199       silc_free(id);
5200       goto out;
5201     }
5202
5203     /* Check the global list as well. */
5204     if (id)
5205       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5206     else
5207       channel = silc_idlist_find_channel_by_name(server->global_list, 
5208                                                  channel_name, NULL);
5209     if (!channel) {
5210       /* Channel really does not exist */
5211       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5212                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5213       goto out;
5214     }
5215   }
5216
5217   /* If the channel is private or secret do not send anything, unless the
5218      user requesting this command is on the channel. */
5219   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5220     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5221         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5222       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5223                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5224       goto out;
5225     }
5226   } else {
5227     if (channel->mode & 
5228         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5229       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5230                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5231       goto out;
5232     }
5233   }
5234
5235   /* Get the users list */
5236   silc_server_get_users_on_channel(server, channel, &client_id_list,
5237                                    &client_mode_list, &list_count);
5238
5239   /* List count */
5240   SILC_PUT32_MSB(list_count, lc);
5241
5242   /* Send reply */
5243   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5244   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5245                                                 SILC_STATUS_OK, ident, 4,
5246                                                 2, idp->data, idp->len,
5247                                                 3, lc, 4,
5248                                                 4, client_id_list->data,
5249                                                 client_id_list->len,
5250                                                 5, client_mode_list->data,
5251                                                 client_mode_list->len);
5252   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5253                           packet->data, packet->len, FALSE);
5254     
5255   silc_buffer_free(idp);
5256   silc_buffer_free(packet);
5257   silc_buffer_free(client_id_list);
5258   silc_buffer_free(client_mode_list);
5259   silc_free(id);
5260
5261  out:
5262   silc_server_command_free(cmd);
5263 }
5264
5265 /* Server side of command GETKEY. This fetches the client's public key
5266    from the server where to the client is connected. */
5267
5268 SILC_SERVER_CMD_FUNC(getkey)
5269 {
5270   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5271   SilcServer server = cmd->server;
5272   SilcBuffer packet;
5273   SilcClientEntry client;
5274   SilcServerEntry server_entry;
5275   SilcClientID *client_id = NULL;
5276   SilcServerID *server_id = NULL;
5277   SilcIDPayload idp = NULL;
5278   uint16 ident = silc_command_get_ident(cmd->payload);
5279   unsigned char *tmp, *pkdata;
5280   uint32 tmp_len, pklen;
5281   SilcBuffer pk = NULL;
5282   SilcIdType id_type;
5283   SilcPublicKey public_key;
5284
5285   SILC_LOG_DEBUG(("Start"));
5286
5287   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5288   if (!tmp) {
5289     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5290                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5291     goto out;
5292   }
5293   idp = silc_id_payload_parse(tmp, tmp_len);
5294   if (!idp) {
5295     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5296                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5297     goto out;
5298   }
5299
5300   id_type = silc_id_payload_get_type(idp);
5301   if (id_type == SILC_ID_CLIENT) {
5302     client_id = silc_id_payload_get_id(idp);
5303
5304     /* If the client is not found from local list there is no chance it
5305        would be locally connected client so send the command further. */
5306     client = silc_idlist_find_client_by_id(server->local_list, 
5307                                            client_id, TRUE, NULL);
5308     if (!client)
5309       client = silc_idlist_find_client_by_id(server->global_list, 
5310                                              client_id, TRUE, NULL);
5311     
5312     if ((!client && !cmd->pending && !server->standalone) ||
5313         (client && !client->connection && !cmd->pending) ||
5314         (client && !client->data.public_key && !cmd->pending)) {
5315       SilcBuffer tmpbuf;
5316       uint16 old_ident;
5317       SilcSocketConnection dest_sock;
5318       
5319       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5320                                                client_id, NULL);
5321       if (!dest_sock)
5322         goto out;
5323       
5324       old_ident = silc_command_get_ident(cmd->payload);
5325       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5326       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5327       
5328       silc_server_packet_send(server, dest_sock,
5329                               SILC_PACKET_COMMAND, cmd->packet->flags,
5330                               tmpbuf->data, tmpbuf->len, TRUE);
5331       
5332       /* Reprocess this packet after received reply from router */
5333       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5334                                   silc_command_get_ident(cmd->payload),
5335                                   silc_server_command_getkey,
5336                                   silc_server_command_dup(cmd));
5337       cmd->pending = TRUE;
5338       silc_command_set_ident(cmd->payload, old_ident);
5339       silc_buffer_free(tmpbuf);
5340       goto out;
5341     }
5342
5343     if (!client) {
5344       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5345                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5346       goto out;
5347     }
5348
5349     /* The client is locally connected, just get the public key and
5350        send it back. If they key does not exist then do not send it, 
5351        send just OK reply */
5352     public_key = client->data.public_key;
5353     if (!public_key) {
5354       pkdata = NULL;
5355       pklen = 0;
5356     } else {
5357       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5358       pk = silc_buffer_alloc(4 + tmp_len);
5359       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5360       silc_buffer_format(pk,
5361                          SILC_STR_UI_SHORT(tmp_len),
5362                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5363                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5364                          SILC_STR_END);
5365       silc_free(tmp);
5366       pkdata = pk->data;
5367       pklen = pk->len;
5368     }
5369   } else if (id_type == SILC_ID_SERVER) {
5370     server_id = silc_id_payload_get_id(idp);
5371
5372     /* If the server is not found from local list there is no chance it
5373        would be locally connected server so send the command further. */
5374     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5375                                                  server_id, TRUE, NULL);
5376     if (!server_entry)
5377       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5378                                                    server_id, TRUE, NULL);
5379     
5380     if (server_entry != server->id_entry &&
5381         ((!server_entry && !cmd->pending && !server->standalone) ||
5382          (server_entry && !server_entry->connection && !cmd->pending &&
5383           !server->standalone) ||
5384          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5385           !server->standalone))) {
5386       SilcBuffer tmpbuf;
5387       uint16 old_ident;
5388       
5389       old_ident = silc_command_get_ident(cmd->payload);
5390       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5391       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5392       
5393       silc_server_packet_send(server, server->router->connection,
5394                               SILC_PACKET_COMMAND, cmd->packet->flags,
5395                               tmpbuf->data, tmpbuf->len, TRUE);
5396       
5397       /* Reprocess this packet after received reply from router */
5398       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5399                                   silc_command_get_ident(cmd->payload),
5400                                   silc_server_command_getkey,
5401                                   silc_server_command_dup(cmd));
5402       cmd->pending = TRUE;
5403       silc_command_set_ident(cmd->payload, old_ident);
5404       silc_buffer_free(tmpbuf);
5405       goto out;
5406     }
5407
5408     if (!server_entry) {
5409       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5410                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5411       goto out;
5412     }
5413
5414     /* If they key does not exist then do not send it, send just OK reply */
5415     public_key = (!server_entry->data.public_key ? 
5416                   (server_entry == server->id_entry ? server->public_key :
5417                    NULL) : server_entry->data.public_key);
5418     if (!public_key) {
5419       pkdata = NULL;
5420       pklen = 0;
5421     } else {
5422       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5423       pk = silc_buffer_alloc(4 + tmp_len);
5424       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5425       silc_buffer_format(pk,
5426                          SILC_STR_UI_SHORT(tmp_len),
5427                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5428                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5429                          SILC_STR_END);
5430       silc_free(tmp);
5431       pkdata = pk->data;
5432       pklen = pk->len;
5433     }
5434   } else {
5435     goto out;
5436   }
5437
5438   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5439   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5440                                                 SILC_STATUS_OK, ident, 
5441                                                 pkdata ? 2 : 1,
5442                                                 2, tmp, tmp_len,
5443                                                 3, pkdata, pklen);
5444   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5445                           packet->data, packet->len, FALSE);
5446   silc_buffer_free(packet);
5447
5448   if (pk)
5449     silc_buffer_free(pk);
5450
5451  out:
5452   if (idp)
5453     silc_id_payload_free(idp);
5454   silc_free(client_id);
5455   silc_free(server_id);
5456   silc_server_command_free(cmd);
5457 }