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