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