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