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