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