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