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