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