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