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