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