Added channel_join_limit, default is 50.
[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 (entry->channels && silc_hash_table_count(entry->channels) >=
2423         server->config->param.chlimit) {
2424       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2425                                             SILC_STATUS_ERR_RESOURCE_LIMIT,
2426                                             0);
2427       goto out;
2428     }
2429 #endif /* SILC_DIST_INPLACE */
2430
2431     silc_free(client_id);
2432     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2433
2434     if (!channel ||
2435         (channel->disabled && server->server_type != SILC_ROUTER)) {
2436       /* Channel not found or not valid */
2437
2438       /* If we are standalone server we don't have a router, we just create
2439          the channel by ourselves (unless it existed). */
2440       if (server->standalone) {
2441         if (!channel) {
2442           channel = silc_server_create_new_channel(server, server->id, cipher,
2443                                                    hmac, channel_name, TRUE);
2444           if (!channel) {
2445             silc_server_command_send_status_data(
2446                                   cmd, SILC_COMMAND_JOIN,
2447                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2448                                   0, 2, cipher, strlen(cipher));
2449             silc_free(client_id);
2450             goto out;
2451           }
2452
2453           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2454           created = TRUE;
2455           create_key = FALSE;
2456         }
2457       } else {
2458
2459         /* The channel does not exist on our server. If we are normal server
2460            we will send JOIN command to our router which will handle the
2461            joining procedure (either creates the channel if it doesn't exist
2462            or joins the client to it). */
2463         if (server->server_type != SILC_ROUTER) {
2464           SilcBuffer tmpbuf;
2465           SilcUInt16 old_ident;
2466
2467           /* If this is pending command callback then we've resolved
2468              it and it didn't work, return since we've notified the
2469              client already in the command reply callback. */
2470           if (cmd->pending) {
2471             silc_free(client_id);
2472             goto out;
2473           }
2474
2475           /* Statistics */
2476           cmd->server->stat.commands_sent++;
2477
2478           old_ident = silc_command_get_ident(cmd->payload);
2479           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2480           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2481
2482           /* Send JOIN command to our router */
2483           silc_server_packet_send(server, (SilcSocketConnection)
2484                                   SILC_PRIMARY_ROUTE(server),
2485                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2486                                   tmpbuf->data, tmpbuf->len, TRUE);
2487
2488           /* Reprocess this packet after received reply from router */
2489           silc_server_command_pending(server, SILC_COMMAND_JOIN,
2490                                       silc_command_get_ident(cmd->payload),
2491                                       silc_server_command_join,
2492                                       silc_server_command_dup(cmd));
2493           cmd->pending = TRUE;
2494           silc_command_set_ident(cmd->payload, old_ident);
2495           silc_buffer_free(tmpbuf);
2496           silc_free(client_id);
2497           goto out;
2498         }
2499
2500         /* We are router and the channel does not seem exist so we will check
2501            our global list as well for the channel. */
2502         channel = silc_idlist_find_channel_by_name(server->global_list,
2503                                                    channel_namec, NULL);
2504         if (!channel) {
2505           /* Channel really does not exist, create it */
2506           channel = silc_server_create_new_channel(server, server->id, cipher,
2507                                                    hmac, channel_name, TRUE);
2508           if (!channel) {
2509             silc_server_command_send_status_data(
2510                                        cmd, SILC_COMMAND_JOIN,
2511                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2512                                        2, cipher, strlen(cipher));
2513             silc_free(client_id);
2514             goto out;
2515           }
2516
2517           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2518           created = TRUE;
2519           create_key = FALSE;
2520         }
2521       }
2522     }
2523   } else {
2524     if (!channel) {
2525       /* Channel not found */
2526
2527       /* If the command came from router and we are normal server then
2528          something went wrong with the joining as the channel was not found.
2529          We can't do anything else but ignore this. */
2530       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2531           server->server_type != SILC_ROUTER) {
2532         silc_free(client_id);
2533         goto out;
2534       }
2535
2536       /* We are router and the channel does not seem exist so we will check
2537          our global list as well for the channel. */
2538       channel = silc_idlist_find_channel_by_name(server->global_list,
2539                                                  channel_namec, NULL);
2540       if (!channel) {
2541         /* Channel really does not exist, create it */
2542         channel = silc_server_create_new_channel(server, server->id, cipher,
2543                                                  hmac, channel_name, TRUE);
2544         if (!channel) {
2545           silc_server_command_send_status_data(
2546                                        cmd, SILC_COMMAND_JOIN,
2547                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2548                                        2, cipher, strlen(cipher));
2549           silc_free(client_id);
2550           goto out;
2551         }
2552
2553         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2554         created = TRUE;
2555         create_key = FALSE;
2556       }
2557     }
2558   }
2559
2560   /* Check whether the channel was created by our router */
2561   if (cmd->pending && context2) {
2562     SilcServerCommandReplyContext reply = context2;
2563
2564     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2565       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2566       SILC_GET32_MSB(created, tmp);
2567       if (silc_argument_get_arg_type(reply->args, 7, NULL))
2568         create_key = FALSE;     /* Router returned the key already */
2569
2570       if (silc_command_get_status(reply->payload, NULL, NULL) &&
2571           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2572         /* Save channel passphrase, if user provided it successfully */
2573         unsigned char *pa;
2574         SilcUInt32 pa_len;
2575         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2576         if (pa) {
2577           silc_free(channel->passphrase);
2578           channel->passphrase = silc_memdup(pa, pa_len);
2579         }
2580       }
2581     }
2582
2583     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2584         !channel->disabled && !silc_hash_table_count(channel->user_list))
2585       created = TRUE;
2586   }
2587
2588   /* If the channel does not have global users and is also empty the client
2589      will be the channel founder and operator. */
2590   if (!channel->disabled &&
2591       !channel->global_users && !silc_hash_table_count(channel->user_list))
2592     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2593
2594   /* Join to the channel */
2595   silc_server_command_join_channel(server, cmd, channel, client_id,
2596                                    created, create_key, umode,
2597                                    auth, auth_len, cauth, cauth_len);
2598
2599   silc_free(client_id);
2600
2601  out:
2602   silc_free(channel_namec);
2603   silc_server_command_free(cmd);
2604 }
2605
2606 /* Server side of command MOTD. Sends server's current "message of the
2607    day" to the client. */
2608
2609 SILC_SERVER_CMD_FUNC(motd)
2610 {
2611   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2612   SilcServer server = cmd->server;
2613   SilcBuffer idp;
2614   char *motd, *dest_server = NULL;
2615   SilcUInt32 motd_len;
2616   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2617
2618   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2619
2620   /* Get server name */
2621   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2622   if (!dest_server) {
2623     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2624                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2625                                           0);
2626     goto out;
2627   }
2628
2629   /* Check server name */
2630   dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2631                                       SILC_STRING_UTF8, 256, NULL);
2632   if (!dest_server) {
2633     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2634                                           SILC_STATUS_ERR_BAD_SERVER,
2635                                           0);
2636     goto out;
2637   }
2638
2639   if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2640     /* Send our MOTD */
2641
2642     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2643
2644     if (server->config && server->config->server_info &&
2645         server->config->server_info->motd_file) {
2646       /* Send motd */
2647       motd = silc_file_readfile(server->config->server_info->motd_file,
2648                                 &motd_len);
2649       if (!motd) {
2650         /* No motd */
2651         silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2652                                        SILC_STATUS_OK, 0, ident, 1,
2653                                        2, idp->data, idp->len);
2654         goto out;
2655       }
2656
2657       motd[motd_len] = 0;
2658       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2659                                      SILC_STATUS_OK, 0, ident, 2,
2660                                      2, idp->data, idp->len,
2661                                      3, motd, motd_len);
2662     } else {
2663       /* No motd */
2664       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2665                                      SILC_STATUS_OK, 0, ident, 1,
2666                                      2, idp->data, idp->len);
2667     }
2668     silc_buffer_free(idp);
2669   } else {
2670     SilcServerEntry entry;
2671
2672     /* Check whether we have this server cached */
2673     entry = silc_idlist_find_server_by_name(server->global_list,
2674                                             dest_server, TRUE, NULL);
2675     if (!entry) {
2676       entry = silc_idlist_find_server_by_name(server->local_list,
2677                                               dest_server, TRUE, NULL);
2678     }
2679
2680     if (server->server_type != SILC_SERVER && !cmd->pending &&
2681         entry && !entry->motd) {
2682       /* Send to the server */
2683       SilcBuffer tmpbuf;
2684       SilcUInt16 old_ident;
2685
2686       /* Statistics */
2687       cmd->server->stat.commands_sent++;
2688
2689       old_ident = silc_command_get_ident(cmd->payload);
2690       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2691       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2692
2693       silc_server_packet_send(server, entry->connection,
2694                               SILC_PACKET_COMMAND, cmd->packet->flags,
2695                               tmpbuf->data, tmpbuf->len, TRUE);
2696
2697       /* Reprocess this packet after received reply from router */
2698       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2699                                   silc_command_get_ident(cmd->payload),
2700                                   silc_server_command_motd,
2701                                   silc_server_command_dup(cmd));
2702       cmd->pending = TRUE;
2703       silc_command_set_ident(cmd->payload, old_ident);
2704       silc_buffer_free(tmpbuf);
2705       goto out;
2706     }
2707
2708     /* Send to primary router only if we don't know the server
2709      * the client requested or if the server is not locally connected */
2710     if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2711         && !cmd->pending && !server->standalone) {
2712       /* Send to the primary router */
2713       SilcBuffer tmpbuf;
2714       SilcUInt16 old_ident;
2715
2716       /* Statistics */
2717       cmd->server->stat.commands_sent++;
2718
2719       old_ident = silc_command_get_ident(cmd->payload);
2720       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2721       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2722
2723       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2724                               SILC_PACKET_COMMAND, cmd->packet->flags,
2725                               tmpbuf->data, tmpbuf->len, TRUE);
2726
2727       /* Reprocess this packet after received reply from router */
2728       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2729                                   silc_command_get_ident(cmd->payload),
2730                                   silc_server_command_motd,
2731                                   silc_server_command_dup(cmd));
2732       cmd->pending = TRUE;
2733       silc_command_set_ident(cmd->payload, old_ident);
2734       silc_buffer_free(tmpbuf);
2735       goto out;
2736     }
2737
2738     if (!entry) {
2739       silc_free(dest_server);
2740       dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2741       silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2742                                            SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2743                                            2, dest_server,
2744                                            strlen(dest_server));
2745       dest_server = NULL;
2746       goto out;
2747     }
2748
2749     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2750     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2751                                    SILC_STATUS_OK, 0, ident, 2,
2752                                    2, idp->data, idp->len,
2753                                    3, entry->motd,
2754                                    entry->motd ?
2755                                    strlen(entry->motd) : 0);
2756     silc_buffer_free(idp);
2757   }
2758
2759  out:
2760   silc_free(dest_server);
2761   silc_server_command_free(cmd);
2762 }
2763
2764 /* Server side of command UMODE. Client can use this command to set/unset
2765    user mode. Client actually cannot set itself to be as server/router
2766    operator so this can be used only to unset the modes. */
2767
2768 SILC_SERVER_CMD_FUNC(umode)
2769 {
2770   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2771   SilcServer server = cmd->server;
2772   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2773   unsigned char *tmp_mask, m[4];
2774   SilcUInt32 mask = 0;
2775   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2776   bool set_mask = FALSE;
2777
2778   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2779     goto out;
2780
2781   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2782
2783   /* Get the client's mode mask */
2784   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2785   if (tmp_mask) {
2786     SILC_GET32_MSB(mask, tmp_mask);
2787     set_mask = TRUE;
2788   }
2789
2790   if (set_mask) {
2791     /* Check that mode changing is allowed. */
2792     if (!silc_server_check_umode_rights(server, client, mask)) {
2793       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2794                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2795       goto out;
2796     }
2797
2798     /* Anonymous mode cannot be set by client */
2799     if (mask & SILC_UMODE_ANONYMOUS &&
2800         !(client->mode & SILC_UMODE_ANONYMOUS)) {
2801       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2802                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2803       goto out;
2804     }
2805
2806     /* Update statistics */
2807     if (mask & SILC_UMODE_GONE) {
2808       if (!(client->mode & SILC_UMODE_GONE))
2809         server->stat.my_aways++;
2810     } else {
2811       if (client->mode & SILC_UMODE_GONE)
2812         server->stat.my_aways--;
2813     }
2814
2815     /* If the client has anonymous mode set, preserve it. */
2816     if (client->mode & SILC_UMODE_ANONYMOUS)
2817       mask |= SILC_UMODE_ANONYMOUS;
2818
2819     /* Change the mode */
2820     client->mode = mask;
2821
2822     /* Send UMODE change to primary router */
2823     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2824                                   SILC_BROADCAST(server), client->id,
2825                                   client->mode);
2826
2827     /* Check if anyone is watching this nickname */
2828     if (server->server_type == SILC_ROUTER)
2829       silc_server_check_watcher_list(server, client, NULL,
2830                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
2831   }
2832
2833   /* Send command reply to sender */
2834   SILC_PUT32_MSB(client->mode, m);
2835   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2836                                  SILC_STATUS_OK, 0, ident, 1,
2837                                  2, m, sizeof(m));
2838
2839  out:
2840   silc_server_command_free(cmd);
2841 }
2842
2843 /* Server side command of CMODE. Changes channel mode */
2844
2845 SILC_SERVER_CMD_FUNC(cmode)
2846 {
2847   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2848   SilcServer server = cmd->server;
2849   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2850   SilcIDListData idata = (SilcIDListData)client;
2851   SilcChannelID *channel_id = NULL;
2852   SilcChannelEntry channel;
2853   SilcChannelClientEntry chl;
2854   SilcBuffer cidp;
2855   unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2856   char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2857   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2858   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2859   bool set_mask = FALSE, set_chpk = FALSE;
2860   SilcPublicKey founder_key = NULL;
2861   SilcBuffer fkey = NULL, chpklist = NULL;
2862   SilcBufferStruct chpk;
2863
2864   if (!client) {
2865     silc_server_command_free(cmd);
2866     return;
2867   }
2868
2869   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2870
2871   /* Get Channel ID */
2872   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2873   if (!tmp_id) {
2874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2875                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2876     silc_server_command_free(cmd);
2877     return;
2878   }
2879   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2880   if (!channel_id) {
2881     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2882                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2883     silc_server_command_free(cmd);
2884     return;
2885   }
2886
2887   /* Get channel entry */
2888   channel = silc_idlist_find_channel_by_id(server->local_list,
2889                                            channel_id, NULL);
2890   if (!channel) {
2891     channel = silc_idlist_find_channel_by_id(server->global_list,
2892                                              channel_id, NULL);
2893     if (!channel) {
2894       silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2895                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2896                                            0, 2, tmp_id, tmp_len2);
2897       silc_free(channel_id);
2898       silc_server_command_free(cmd);
2899       return;
2900     }
2901   }
2902   old_mask = channel->mode;
2903
2904   /* Get the channel mode mask */
2905   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2906   if (tmp_mask) {
2907     SILC_GET32_MSB(mode_mask, tmp_mask);
2908     set_mask = TRUE;
2909   }
2910
2911   /* Check whether this client is on the channel */
2912   if (!silc_server_client_on_channel(client, channel, &chl)) {
2913     silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2914                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2915                                          2, tmp_id, tmp_len2);
2916     goto out;
2917   }
2918
2919   /* Check that client has rights to change any requested channel modes */
2920   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2921                                                   mode_mask)) {
2922     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2923     silc_server_command_send_status_data(
2924                              cmd, SILC_COMMAND_CMODE,
2925                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2926                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2927                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2928                              2, tmp_id, tmp_len2);
2929     goto out;
2930   }
2931
2932   /* If mode mask was not sent as argument then merely return the current
2933      mode mask, founder key and channel public key list to the sender. */
2934   if (!set_mask) {
2935     unsigned char m[4];
2936     SILC_PUT32_MSB(channel->mode, m);
2937     if (channel->founder_key)
2938       fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2939     if (channel->channel_pubkeys)
2940       chpklist = silc_server_get_channel_pk_list(server, channel,
2941                                                  FALSE, FALSE);
2942     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
2943                                    SILC_STATUS_OK, 0, ident, 4,
2944                                    2, tmp_id, tmp_len2,
2945                                    3, m, sizeof(m),
2946                                    4, fkey ? fkey->data : NULL,
2947                                    fkey ? fkey->len : 0,
2948                                    5, chpklist ? chpklist->data : NULL,
2949                                    chpklist ? chpklist->len : 0);
2950     goto out;
2951   }
2952
2953   /*
2954    * Check the modes. Modes that requires nothing special operation are
2955    * not checked here.
2956    */
2957
2958   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2959     /* Channel uses private keys to protect traffic. Client(s) has set the
2960        key locally they want to use, server does not know that key. */
2961     /* Nothing interesting to do here */
2962   } else {
2963     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2964       /* The mode is removed and we need to generate and distribute
2965          new channel key. Clients are not using private channel keys
2966          anymore after this. */
2967
2968       /* Re-generate channel key */
2969       if (!silc_server_create_channel_key(server, channel, 0))
2970         goto out;
2971
2972       /* Send the channel key. This sends it to our local clients and if
2973          we are normal server to our router as well. */
2974       silc_server_send_channel_key(server, NULL, channel,
2975                                    server->server_type == SILC_ROUTER ?
2976                                    FALSE : !server->standalone);
2977
2978       cipher = (char *)silc_cipher_get_name(channel->channel_key);
2979       hmac = (char *)silc_hmac_get_name(channel->hmac);
2980     }
2981   }
2982
2983   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2984     /* User limit is set on channel */
2985     SilcUInt32 user_limit;
2986
2987     /* Get user limit */
2988     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2989     if (!tmp) {
2990       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2991         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2992                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2993         goto out;
2994       }
2995     } else {
2996       SILC_GET32_MSB(user_limit, tmp);
2997       channel->user_limit = user_limit;
2998     }
2999   } else {
3000     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3001       /* User limit mode is unset. Remove user limit */
3002       channel->user_limit = 0;
3003   }
3004
3005   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3006     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3007       /* Passphrase has been set to channel */
3008
3009       /* Get the passphrase */
3010       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3011       if (!tmp) {
3012         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3013                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3014         goto out;
3015       }
3016
3017       /* Save the passphrase */
3018       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3019     }
3020   } else {
3021     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3022       /* Passphrase mode is unset. remove the passphrase */
3023       silc_free(channel->passphrase);
3024       channel->passphrase = NULL;
3025     }
3026   }
3027
3028   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3029     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3030       /* Cipher to use protect the traffic */
3031       SilcCipher newkey, oldkey;
3032
3033       /* Get cipher */
3034       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3035       if (!cipher) {
3036         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3037                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3038         goto out;
3039       }
3040
3041       /* Delete old cipher and allocate the new one */
3042       if (!silc_cipher_alloc(cipher, &newkey)) {
3043         silc_server_command_send_status_data(
3044                                          cmd, SILC_COMMAND_CMODE,
3045                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3046                                          2, cipher, strlen(cipher));
3047         goto out;
3048       }
3049
3050       oldkey = channel->channel_key;
3051       channel->channel_key = newkey;
3052
3053       /* Re-generate channel key */
3054       if (!silc_server_create_channel_key(server, channel, 0)) {
3055         /* We don't have new key, revert to old one */
3056         channel->channel_key = oldkey;
3057         goto out;
3058       }
3059
3060       /* Remove old channel key for good */
3061       silc_cipher_free(oldkey);
3062
3063       /* Send the channel key. This sends it to our local clients and if
3064          we are normal server to our router as well. */
3065       silc_server_send_channel_key(server, NULL, channel,
3066                                    server->server_type == SILC_ROUTER ?
3067                                    FALSE : !server->standalone);
3068     }
3069   } else {
3070     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3071       /* Cipher mode is unset. Remove the cipher and revert back to
3072          default cipher */
3073       SilcCipher newkey, oldkey;
3074       cipher = channel->cipher;
3075
3076       /* Delete old cipher and allocate default one */
3077       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3078         silc_server_command_send_status_data(
3079                                       cmd, SILC_COMMAND_CMODE,
3080                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3081                                       2, cipher, strlen(cipher));
3082         goto out;
3083       }
3084
3085       oldkey = channel->channel_key;
3086       channel->channel_key = newkey;
3087
3088       /* Re-generate channel key */
3089       if (!silc_server_create_channel_key(server, channel, 0)) {
3090         /* We don't have new key, revert to old one */
3091         channel->channel_key = oldkey;
3092         goto out;
3093       }
3094
3095       /* Remove old channel key for good */
3096       silc_cipher_free(oldkey);
3097
3098       /* Send the channel key. This sends it to our local clients and if
3099          we are normal server to our router as well. */
3100       silc_server_send_channel_key(server, NULL, channel,
3101                                    server->server_type == SILC_ROUTER ?
3102                                    FALSE : !server->standalone);
3103     }
3104   }
3105
3106   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3107     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3108       /* HMAC to use protect the traffic */
3109       unsigned char hash[32];
3110       SilcHmac newhmac;
3111
3112       /* Get hmac */
3113       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3114       if (!hmac) {
3115         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3116                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3117         goto out;
3118       }
3119
3120       /* Delete old hmac and allocate the new one */
3121       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3122         silc_server_command_send_status_data(
3123                                         cmd, SILC_COMMAND_CMODE,
3124                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3125                                         2, hmac, strlen(hmac));
3126         goto out;
3127       }
3128
3129       silc_hmac_free(channel->hmac);
3130       channel->hmac = newhmac;
3131
3132       /* Set the HMAC key out of current channel key. The client must do
3133          this locally. */
3134       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3135                      channel->key_len / 8, hash);
3136       silc_hmac_set_key(channel->hmac, hash,
3137                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3138       memset(hash, 0, sizeof(hash));
3139     }
3140   } else {
3141     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3142       /* Hmac mode is unset. Remove the hmac and revert back to
3143          default hmac */
3144       SilcHmac newhmac;
3145       unsigned char hash[32];
3146       hmac = channel->hmac_name;
3147
3148       /* Delete old hmac and allocate default one */
3149       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3150         silc_server_command_send_status_data(
3151                                         cmd, SILC_COMMAND_CMODE,
3152                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3153                                         2, hmac, strlen(hmac));
3154         goto out;
3155       }
3156
3157       silc_hmac_free(channel->hmac);
3158       channel->hmac = newhmac;
3159
3160       /* Set the HMAC key out of current channel key. The client must do
3161          this locally. */
3162       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3163                      channel->key_len / 8,
3164                      hash);
3165       silc_hmac_set_key(channel->hmac, hash,
3166                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3167       memset(hash, 0, sizeof(hash));
3168     }
3169   }
3170
3171   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3172     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3173       /* Check if the founder public key was received */
3174       founder_key = idata->public_key;
3175       tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3176       if (tmp) {
3177         if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3178           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3179                                                 SILC_STATUS_ERR_AUTH_FAILED,
3180                                                 0);
3181           goto out;
3182         }
3183       } else {
3184         /* If key was not sent and the channel mode has already founder
3185            then the key was not to be changed. */
3186         if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3187           goto has_founder;
3188       }
3189
3190       /* Set the founder authentication */
3191       tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3192       if (!tmp) {
3193         silc_server_command_send_status_reply(
3194                                      cmd, SILC_COMMAND_CMODE,
3195                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3196         goto out;
3197       }
3198
3199       /* Verify the payload before setting the mode */
3200       if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3201                                  founder_key, 0, server->sha1hash,
3202                                  client->id, SILC_ID_CLIENT)) {
3203         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3204                                               SILC_STATUS_ERR_AUTH_FAILED,
3205                                               0);
3206         goto out;
3207       }
3208
3209       /* Save the public key */
3210       if (channel->founder_key)
3211         silc_pkcs_public_key_free(channel->founder_key);
3212       if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3213         channel->founder_key = founder_key;
3214       else
3215         channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3216       if (!channel->founder_key) {
3217         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3218                                               SILC_STATUS_ERR_AUTH_FAILED,
3219                                               0);
3220         goto out;
3221       }
3222
3223       fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3224       if (!fkey) {
3225         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3226                                               SILC_STATUS_ERR_AUTH_FAILED,
3227                                               0);
3228         silc_pkcs_public_key_free(channel->founder_key);
3229         channel->founder_key = NULL;
3230         goto out;
3231       }
3232     }
3233   } else {
3234     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3235       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3236         if (channel->founder_key)
3237           silc_pkcs_public_key_free(channel->founder_key);
3238         channel->founder_key = NULL;
3239       }
3240     }
3241   }
3242  has_founder:
3243
3244   if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3245     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3246       SilcStatus st;
3247
3248       chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3249
3250       if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3251         goto has_pk_list;
3252
3253       set_chpk = TRUE;
3254
3255       /* Process the channel public key(s) */
3256       st = silc_server_set_channel_pk_list(server, NULL, channel,
3257                                            chpkdata, chpklen);
3258       if (st != SILC_STATUS_OK) {
3259         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3260         goto out;
3261       }
3262     }
3263   } else {
3264     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3265       if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3266         if (channel->channel_pubkeys)
3267           silc_hash_table_free(channel->channel_pubkeys);
3268         channel->channel_pubkeys = NULL;
3269         set_chpk = TRUE;
3270       }
3271     }
3272   }
3273  has_pk_list:
3274
3275   /* Finally, set the mode */
3276   old_mask = channel->mode = mode_mask;
3277
3278   /* Send CMODE_CHANGE notify. */
3279   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3280   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3281     SILC_PUT32_MSB(channel->user_limit, ulimit);
3282   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3283                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3284                                      cidp->data, cidp->len,
3285                                      tmp_mask, 4,
3286                                      cipher, cipher ? strlen(cipher) : 0,
3287                                      hmac, hmac ? strlen(hmac) : 0,
3288                                      passphrase, passphrase ?
3289                                      strlen(passphrase) : 0,
3290                                      fkey ? fkey->data : NULL,
3291                                      fkey ? fkey->len : 0,
3292                                      chpkdata ? chpkdata : NULL,
3293                                      chpkdata ? chpklen : 0,
3294                                      mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3295                                      ulimit : NULL,
3296                                      mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3297                                      sizeof(ulimit) : 0);
3298
3299   /* Set CMODE notify type to network */
3300   if (chpkdata && chpklen)
3301     silc_buffer_set(&chpk, chpkdata, chpklen);
3302   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3303                                 SILC_BROADCAST(server), channel,
3304                                 mode_mask, client->id, SILC_ID_CLIENT,
3305                                 cipher, hmac, passphrase, founder_key,
3306                                 chpkdata ? &chpk : NULL);
3307
3308   if (set_chpk)
3309     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3310
3311   /* Send command reply to sender */
3312   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3313                                  SILC_STATUS_OK, 0, ident, 5,
3314                                  2, tmp_id, tmp_len2,
3315                                  3, tmp_mask, 4,
3316                                  4, fkey ? fkey->data : NULL,
3317                                  fkey ? fkey->len : 0,
3318                                  5, chpklist ? chpklist->data :
3319                                  NULL, chpklist ? chpklist->len
3320                                  : 0,
3321                                  6, (mode_mask &
3322                                      SILC_CHANNEL_MODE_ULIMIT ?
3323                                      ulimit : NULL),
3324                                  (mode_mask &
3325                                   SILC_CHANNEL_MODE_ULIMIT ?
3326                                   sizeof(ulimit) : 0));
3327   silc_buffer_free(cidp);
3328
3329  out:
3330   channel->mode = old_mask;
3331   silc_buffer_free(chpklist);
3332   silc_buffer_free(fkey);
3333   silc_free(channel_id);
3334   silc_server_command_free(cmd);
3335 }
3336
3337 /* Server side of CUMODE command. Changes client's mode on a channel. */
3338
3339 SILC_SERVER_CMD_FUNC(cumode)
3340 {
3341   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3342   SilcServer server = cmd->server;
3343   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3344   SilcChannelID *channel_id = NULL;
3345   SilcClientID *client_id = NULL;
3346   SilcChannelEntry channel;
3347   SilcClientEntry target_client;
3348   SilcChannelClientEntry chl;
3349   SilcBuffer idp;
3350   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3351   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3352   int notify = FALSE;
3353   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3354   SilcPublicKey founder_key = NULL;
3355   SilcBuffer fkey = NULL;
3356
3357   if (!client)
3358     goto out;
3359
3360   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3361
3362   /* Get Channel ID */
3363   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3364   if (!tmp_ch_id) {
3365     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3366                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3367     goto out;
3368   }
3369   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3370   if (!channel_id) {
3371     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3372                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3373     goto out;
3374   }
3375
3376   /* Get channel entry */
3377   channel = silc_idlist_find_channel_by_id(server->local_list,
3378                                            channel_id, NULL);
3379   if (!channel) {
3380     channel = silc_idlist_find_channel_by_id(server->global_list,
3381                                              channel_id, NULL);
3382     if (!channel) {
3383       silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3384                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3385                                            0, 2, tmp_ch_id, tmp_ch_len);
3386       goto out;
3387     }
3388   }
3389
3390   /* Check whether sender is on the channel */
3391   if (!silc_server_client_on_channel(client, channel, &chl)) {
3392     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3393                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3394                                          2, tmp_ch_id, tmp_ch_len);
3395     goto out;
3396   }
3397   sender_mask = chl->mode;
3398
3399   /* Get the target client's channel mode mask */
3400   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3401   if (!tmp_mask) {
3402     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3403                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3404                                           0);
3405     goto out;
3406   }
3407   SILC_GET32_MSB(target_mask, tmp_mask);
3408
3409   /* Get target Client ID */
3410   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3411   if (!tmp_id) {
3412     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3413                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3414     goto out;
3415   }
3416   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3417   if (!client_id) {
3418     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3419                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3420     goto out;
3421   }
3422
3423   /* Get target client's entry */
3424   target_client = silc_idlist_find_client_by_id(server->local_list,
3425                                                 client_id, TRUE, NULL);
3426   if (!target_client)
3427     target_client = silc_idlist_find_client_by_id(server->global_list,
3428                                                   client_id, TRUE, NULL);
3429
3430   if (target_client != client &&
3431       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3432       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3433     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3434                                          SILC_STATUS_ERR_NOT_YOU, 0,
3435                                          2, tmp_ch_id, tmp_ch_len);
3436     goto out;
3437   }
3438
3439   /* Check whether target client is on the channel */
3440   if (target_client != client) {
3441     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3442       silc_server_command_send_status_data2(
3443                                   cmd, SILC_COMMAND_CUMODE,
3444                                   SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3445                                   2, tmp_id, tmp_len,
3446                                   3, tmp_ch_id, tmp_ch_len);
3447       goto out;
3448     }
3449   }
3450
3451   /*
3452    * Change the mode
3453    */
3454
3455   /* If the target client is founder, no one else can change their mode
3456      but themselves. */
3457   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3458     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3459                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3460                                          0, 2, tmp_ch_id, tmp_ch_len);
3461     goto out;
3462   }
3463
3464   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3465     if (target_client != client) {
3466       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3467                                             SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3468                                             0);
3469       goto out;
3470     }
3471
3472     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3473       /* The client tries to claim the founder rights. */
3474       unsigned char *tmp_auth;
3475       SilcUInt32 tmp_auth_len;
3476       SilcChannelClientEntry chl2;
3477       SilcHashTableList htl;
3478
3479       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3480           !channel->founder_key) {
3481         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3482                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3483         goto out;
3484       }
3485
3486       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3487       if (!tmp_auth) {
3488         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3489                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3490         goto out;
3491       }
3492
3493       /* Verify the authentication payload */
3494       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3495                                  channel->founder_key, 0, server->sha1hash,
3496                                  client->id, SILC_ID_CLIENT)) {
3497         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3498                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3499         goto out;
3500       }
3501
3502       notify = TRUE;
3503       founder_key = channel->founder_key;
3504       fkey = silc_pkcs_public_key_payload_encode(founder_key);
3505       if (!fkey) {
3506         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3507                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3508         goto out;
3509       }
3510
3511       /* There cannot be anyone else as founder on the channel now.  This
3512          client is definitely the founder due to this authentication.  This
3513          is done only on router, not on server, since server cannot know
3514          whether router will accept this mode change or not.  XXX This
3515          probably shouldn't be done anymore at all, may cause problems in
3516          router-router connections too (maybe just AUTH_FAILED error should
3517          be returned). -Pekka */
3518       if (server->server_type == SILC_ROUTER) {
3519         silc_hash_table_list(channel->user_list, &htl);
3520         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3521           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3522             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3523             silc_server_force_cumode_change(server, NULL, channel, chl2,
3524                                             chl2->mode);
3525             break;
3526           }
3527         silc_hash_table_list_reset(&htl);
3528       }
3529
3530       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3531     }
3532   } else {
3533     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3534       if (target_client == client) {
3535         /* Remove channel founder rights from itself */
3536         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3537         notify = TRUE;
3538       } else {
3539         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3540                                               SILC_STATUS_ERR_NOT_YOU, 0);
3541         goto out;
3542       }
3543     }
3544   }
3545
3546   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3547     /* Promote to operator */
3548     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3549       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3550           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3551         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3552                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3553                                              0, 2, tmp_ch_id, tmp_ch_len);
3554         goto out;
3555       }
3556
3557       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3558       notify = TRUE;
3559     }
3560   } else {
3561     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3562       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3563           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3564         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3565                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3566                                              0, 2, tmp_ch_id, tmp_ch_len);
3567         goto out;
3568       }
3569
3570       /* Demote to normal user */
3571       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3572       notify = TRUE;
3573     }
3574   }
3575
3576   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3577     if (target_client != client) {
3578       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3579                                             SILC_STATUS_ERR_NOT_YOU, 0);
3580       goto out;
3581     }
3582
3583     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3584       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3585       notify = TRUE;
3586     }
3587   } else {
3588     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3589       if (target_client != client) {
3590         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3591                                               SILC_STATUS_ERR_NOT_YOU, 0);
3592         goto out;
3593       }
3594
3595       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3596       notify = TRUE;
3597     }
3598   }
3599
3600   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3601     if (target_client != client) {
3602       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3603                                             SILC_STATUS_ERR_NOT_YOU, 0);
3604       goto out;
3605     }
3606
3607     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3608       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3609       notify = TRUE;
3610     }
3611   } else {
3612     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3613       if (target_client != client) {
3614         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3615                                               SILC_STATUS_ERR_NOT_YOU, 0);
3616         goto out;
3617       }
3618
3619       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3620       notify = TRUE;
3621     }
3622   }
3623
3624   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3625     if (target_client != client) {
3626       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3627                                             SILC_STATUS_ERR_NOT_YOU, 0);
3628       goto out;
3629     }
3630
3631     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3632       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3633       notify = TRUE;
3634     }
3635   } else {
3636     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3637       if (target_client != client) {
3638         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3639                                               SILC_STATUS_ERR_NOT_YOU, 0);
3640         goto out;
3641       }
3642
3643       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3644       notify = TRUE;
3645     }
3646   }
3647
3648   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3649     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3650       if (client == target_client) {
3651         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3652                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3653         goto out;
3654       }
3655       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3656       notify = TRUE;
3657     }
3658   } else {
3659     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3660       if (client == target_client) {
3661         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3662                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3663         goto out;
3664       }
3665       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3666       notify = TRUE;
3667     }
3668   }
3669
3670   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3671   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3672
3673   /* Send notify to channel, notify only if mode was actually changed. */
3674   if (notify) {
3675     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3676                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3677                                        idp->data, idp->len,
3678                                        tmp_mask, 4,
3679                                        tmp_id, tmp_len,
3680                                        fkey ? fkey->data : NULL,
3681                                        fkey ? fkey->len : 0);
3682
3683     /* Set CUMODE notify type to network */
3684     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3685                                    SILC_BROADCAST(server), channel,
3686                                    target_mask, client->id, SILC_ID_CLIENT,
3687                                    target_client->id, founder_key);
3688   }
3689
3690   /* Send command reply to sender */
3691   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3692                                  SILC_STATUS_OK, 0, ident, 3,
3693                                  2, tmp_mask, 4,
3694                                  3, tmp_ch_id, tmp_ch_len,
3695                                  4, tmp_id, tmp_len);
3696   silc_buffer_free(idp);
3697
3698  out:
3699   silc_free(channel_id);
3700   silc_free(client_id);
3701   silc_buffer_free(fkey);
3702   silc_server_command_free(cmd);
3703 }
3704
3705 /* Server side of KICK command. Kicks client out of channel. */
3706
3707 SILC_SERVER_CMD_FUNC(kick)
3708 {
3709   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3710   SilcServer server = cmd->server;
3711   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3712   SilcClientEntry target_client;
3713   SilcChannelID *channel_id;
3714   SilcClientID *client_id;
3715   SilcChannelEntry channel;
3716   SilcChannelClientEntry chl;
3717   SilcBuffer idp;
3718   SilcUInt32 tmp_len, target_idp_len, clen;
3719   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3720   unsigned char *tmp, *comment, *target_idp;
3721
3722   if (!client)
3723     goto out;
3724
3725   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3726
3727   /* Get Channel ID */
3728   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3729   if (!tmp) {
3730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3731                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3732     goto out;
3733   }
3734   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3735   if (!channel_id) {
3736     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3737                                          SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
3738                                          2, tmp, tmp_len);
3739     goto out;
3740   }
3741
3742   /* Get channel entry */
3743   channel = silc_idlist_find_channel_by_id(server->local_list,
3744                                            channel_id, NULL);
3745   if (!channel) {
3746     channel = silc_idlist_find_channel_by_id(server->local_list,
3747                                              channel_id, NULL);
3748     if (!channel) {
3749       silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3750                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3751                                            0, 2, tmp, tmp_len);
3752       goto out;
3753     }
3754   }
3755
3756   /* Check whether sender is on the channel */
3757   if (!silc_server_client_on_channel(client, channel, &chl)) {
3758     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3759                                          SILC_STATUS_ERR_NOT_ON_CHANNEL,
3760                                          0, 2, tmp, tmp_len);
3761     goto out;
3762   }
3763
3764   /* Check that the kicker is channel operator or channel founder */
3765   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3766       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3767     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3768                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3769                                          0, 2, tmp, tmp_len);
3770     goto out;
3771   }
3772
3773   /* Get target Client ID */
3774   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3775   if (!target_idp) {
3776     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3777                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3778     goto out;
3779   }
3780   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3781   if (!client_id) {
3782     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3783                                          SILC_STATUS_ERR_BAD_CLIENT_ID,
3784                                          0, 2, target_idp, target_idp_len);
3785     goto out;
3786   }
3787
3788   /* Get target client's entry */
3789   target_client = silc_idlist_find_client_by_id(server->local_list,
3790                                                 client_id, TRUE, NULL);
3791   if (!target_client) {
3792     target_client = silc_idlist_find_client_by_id(server->global_list,
3793                                                   client_id, TRUE, NULL);
3794   }
3795
3796   /* Check whether target client is on the channel */
3797   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3798     silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3799                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3800                                           0, 2, target_idp, target_idp_len,
3801                                           3, tmp, tmp_len);
3802     goto out;
3803   }
3804
3805   /* Check that the target client is not channel founder. Channel founder
3806      cannot be kicked from the channel. */
3807   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3808     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3809                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3810                                          0, 2, tmp, tmp_len);
3811     goto out;
3812   }
3813
3814   /* Get comment */
3815   comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3816   if (clen > 128)
3817     comment = NULL;
3818
3819
3820   /* Send the reply back to the client */
3821   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3822                                  SILC_STATUS_OK, 0, ident, 2,
3823                                  2, tmp, tmp_len,
3824                                  3, target_idp, target_idp_len);
3825
3826   /* Send KICKED notify to local clients on the channel */
3827   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3828   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3829                                      SILC_NOTIFY_TYPE_KICKED, 3,
3830                                      target_idp, target_idp_len,
3831                                      comment, comment ? strlen(comment) : 0,
3832                                      idp->data, idp->len);
3833   silc_buffer_free(idp);
3834
3835   /* Send KICKED notify to primary route */
3836   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3837                                  SILC_BROADCAST(server), channel,
3838                                  target_client->id, client->id, comment);
3839
3840   /* Remove the client from channel's invite list */
3841   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3842     SilcBuffer ab =
3843       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3844     SilcArgumentPayload args =
3845       silc_argument_payload_parse(ab->data, ab->len, 1);
3846
3847     silc_server_inviteban_process(server, channel->invite_list, 1, args);
3848     silc_buffer_free(ab);
3849     silc_argument_payload_free(args);
3850   }
3851
3852   /* Remove the client from the channel. If the channel does not exist
3853      after removing the client then the client kicked itself off the channel
3854      and we don't have to send anything after that. */
3855   if (!silc_server_remove_from_one_channel(server, NULL, channel,
3856                                            target_client, FALSE))
3857     goto out;
3858
3859   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3860     /* Re-generate channel key */
3861     if (!silc_server_create_channel_key(server, channel, 0))
3862       goto out;
3863
3864     /* Send the channel key to the channel. The key of course is not sent
3865        to the client who was kicked off the channel. */
3866     silc_server_send_channel_key(server, target_client->connection, channel,
3867                                  server->server_type == SILC_ROUTER ?
3868                                  FALSE : !server->standalone);
3869   }
3870
3871  out:
3872   silc_server_command_free(cmd);
3873 }
3874
3875 /* Server side of OPER command. Client uses this comand to obtain server
3876    operator privileges to this server/router. */
3877
3878 SILC_SERVER_CMD_FUNC(oper)
3879 {
3880   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3881   SilcServer server = cmd->server;
3882   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3883   unsigned char *username = NULL, *auth;
3884   SilcUInt32 tmp_len;
3885   SilcServerConfigAdmin *admin;
3886   SilcIDListData idata = (SilcIDListData)client;
3887   bool result = FALSE;
3888   SilcPublicKey cached_key;
3889
3890   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3891     goto out;
3892
3893   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3894
3895   /* Get the username */
3896   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3897   if (!username) {
3898     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3899                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3900                                           0);
3901     goto out;
3902   }
3903
3904   /* Check username */
3905   username = silc_identifier_check(username, strlen(username),
3906                                    SILC_STRING_UTF8, 128, &tmp_len);
3907   if (!username) {
3908     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3909                                           SILC_STATUS_ERR_BAD_USERNAME,
3910                                           0);
3911     goto out;
3912   }
3913
3914   /* Get the admin configuration */
3915   admin = silc_server_config_find_admin(server, cmd->sock->ip,
3916                                         username, client->nickname);
3917   if (!admin) {
3918     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3919                                           username, client->nickname);
3920     if (!admin) {
3921       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3922                                             SILC_STATUS_ERR_AUTH_FAILED,
3923                                             0);
3924       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3925                      "nickname '%s' from %s", username,
3926                      client->nickname, cmd->sock->hostname));
3927       goto out;
3928     }
3929   }
3930
3931   /* Get the authentication payload */
3932   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3933   if (!auth) {
3934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3935                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3936                                           0);
3937     goto out;
3938   }
3939
3940   /* Verify the authentication data. If both passphrase and public key
3941      is set then try both of them. */
3942   if (admin->passphrase)
3943     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3944                                    admin->passphrase, admin->passphrase_len,
3945                                    idata->hash, client->id, SILC_ID_CLIENT);
3946   if (!result && admin->publickeys) {
3947     cached_key = silc_server_get_public_key(server, admin->publickeys);
3948     if (!cached_key)
3949       goto out;
3950     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3951                                    cached_key, 0, idata->hash,
3952                                    client->id, SILC_ID_CLIENT);
3953   }
3954   if (!result) {
3955     /* Authentication failed */
3956     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3957                                           SILC_STATUS_ERR_AUTH_FAILED,
3958                                           0);
3959     goto out;
3960   }
3961
3962   /* Client is now server operator */
3963   client->mode |= SILC_UMODE_SERVER_OPERATOR;
3964
3965   /* Update statistics */
3966   if (SILC_IS_LOCAL(client))
3967     server->stat.my_server_ops++;
3968   if (server->server_type == SILC_ROUTER)
3969     server->stat.server_ops++;
3970
3971   /* Send UMODE change to primary router */
3972   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3973                                 SILC_BROADCAST(server), client->id,
3974                                 client->mode);
3975
3976   /* Check if anyone is watching this nickname */
3977   if (server->server_type == SILC_ROUTER)
3978     silc_server_check_watcher_list(server, client, NULL,
3979                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3980
3981   /* Send reply to the sender */
3982   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3983                                         SILC_STATUS_OK, 0);
3984
3985  out:
3986   silc_free(username);
3987   silc_server_command_free(cmd);
3988 }
3989
3990 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3991 {
3992   SilcServer server = app_context;
3993   QuitInternal q = (QuitInternal)context;
3994   SilcClientID *client_id = (SilcClientID *)q->sock;
3995   SilcClientEntry client;
3996   SilcSocketConnection sock;
3997
3998   client = silc_idlist_find_client_by_id(server->local_list, client_id,
3999                                          TRUE, NULL);
4000   if (client && client->connection) {
4001     sock = client->connection;
4002
4003     /* If there is pending outgoing data for the client then purge it
4004        to the network before closing connection. */
4005     silc_server_packet_queue_purge(server, sock);
4006
4007     /* Close the connection on our side */
4008     client->router = NULL;
4009     client->connection = NULL;
4010     sock->user_data = NULL;
4011     silc_server_close_connection(server, sock);
4012   }
4013
4014   silc_free(client_id);
4015   silc_free(q);
4016 }
4017
4018 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4019 {
4020   SilcServer server = app_context;
4021   QuitInternal q = (QuitInternal)context;
4022   SilcClientID *client_id = (SilcClientID *)q->sock;
4023   SilcClientEntry client;
4024
4025   client = silc_idlist_find_client_by_id(server->local_list, client_id,
4026                                          TRUE, NULL);
4027   if (client && client->mode & SILC_UMODE_DETACHED) {
4028     SILC_LOG_DEBUG(("Detach timeout"));
4029     silc_server_free_client_data(server, NULL, client, TRUE,
4030                                  "Detach timeout");
4031   }
4032
4033   silc_free(client_id);
4034   silc_free(q);
4035 }
4036
4037 /* Server side of DETACH command.  Detached the client from the network
4038    by closing the connection but preserving the session. */
4039
4040 SILC_SERVER_CMD_FUNC(detach)
4041 {
4042   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4043   SilcServer server = cmd->server;
4044   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4045   QuitInternal q;
4046
4047   if (server->config->detach_disabled) {
4048     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4049                                           SILC_STATUS_ERR_OPERATION_ALLOWED,
4050                                           0);
4051     goto out;
4052   }
4053
4054   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4055     goto out;
4056
4057   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4058
4059   /* Remove operator privileges, since the client may resume in some
4060      other server which to it does not have operator privileges. */
4061   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4062   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4063
4064   /* Send the user mode notify to notify that client is detached */
4065   client->mode |= SILC_UMODE_DETACHED;
4066   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4067   client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4068   client->last_command = 0;
4069   client->fast_command = 0;
4070   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4071                                 SILC_BROADCAST(server), client->id,
4072                                 client->mode);
4073   server->stat.my_detached++;
4074
4075   /* Check if anyone is watching this nickname */
4076   if (server->server_type == SILC_ROUTER)
4077     silc_server_check_watcher_list(server, client, NULL,
4078                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4079
4080   q = silc_calloc(1, sizeof(*q));
4081   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4082   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4083                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4084
4085   if (server->config->detach_timeout) {
4086     q = silc_calloc(1, sizeof(*q));
4087     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4088     silc_schedule_task_add(server->schedule, 0,
4089                            silc_server_command_detach_timeout,
4090                            q, server->config->detach_timeout * 60,
4091                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4092   }
4093
4094   /* Send reply to the sender */
4095   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4096                                         SILC_STATUS_OK, 0);
4097
4098  out:
4099   silc_server_command_free(cmd);
4100 }
4101
4102 /* Server side of WATCH command. */
4103
4104 SILC_SERVER_CMD_FUNC(watch)
4105 {
4106   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4107   SilcServer server = cmd->server;
4108   char *add_nick, *del_nick;
4109   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4110   unsigned char hash[16], *tmp,  *pk, *nick;
4111   SilcClientEntry client;
4112   SilcClientID *client_id = NULL;
4113   SilcUInt16 old_ident;
4114
4115   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4116
4117   if (server->server_type != SILC_ROUTER && !server->standalone) {
4118     if (!cmd->pending) {
4119       /* Send the command to router */
4120       SilcBuffer tmpbuf;
4121
4122       /* If backup receives this from primary, handle it locally */
4123       if (server->server_type == SILC_BACKUP_ROUTER &&
4124           cmd->sock == SILC_PRIMARY_ROUTE(server))
4125         goto process_watch;
4126
4127       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4128
4129       /* Statistics */
4130       cmd->server->stat.commands_sent++;
4131
4132       old_ident = silc_command_get_ident(cmd->payload);
4133       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4134       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4135
4136       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4137                               SILC_PACKET_COMMAND, cmd->packet->flags,
4138                               tmpbuf->data, tmpbuf->len, TRUE);
4139
4140       /* Reprocess this packet after received reply from router */
4141       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4142                                   silc_command_get_ident(cmd->payload),
4143                                   silc_server_command_watch,
4144                                   silc_server_command_dup(cmd));
4145       cmd->pending = TRUE;
4146       silc_command_set_ident(cmd->payload, old_ident);
4147       silc_buffer_free(tmpbuf);
4148       goto out;
4149     } else {
4150       SilcServerCommandReplyContext reply = context2;
4151       SilcStatus status;
4152
4153       if (!reply)
4154         goto out;
4155
4156       silc_command_get_status(reply->payload, &status, NULL);
4157
4158       /* Backup router handles the WATCH command also. */
4159       if (server->server_type != SILC_BACKUP_ROUTER ||
4160           SILC_STATUS_IS_ERROR(status)) {
4161         /* Received reply from router, just send same data to the client. */
4162         SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4163         silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4164                                               0);
4165         goto out;
4166       }
4167     }
4168   }
4169
4170   /* We are router and keep the watch list for local cell */
4171  process_watch:
4172
4173   /* Get the client ID */
4174   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4175   if (!tmp) {
4176     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4177                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4178                                           0);
4179     goto out;
4180   }
4181   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4182   if (!client_id) {
4183     silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4184                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4185                                          0, 2, tmp, tmp_len);
4186     goto out;
4187   }
4188
4189   /* Get the client entry which must be in local list */
4190   client = silc_idlist_find_client_by_id(server->local_list,
4191                                          client_id, TRUE, NULL);
4192   if (!client) {
4193     /* Backup checks global list also */
4194     if (server->server_type == SILC_BACKUP_ROUTER)
4195       client = silc_idlist_find_client_by_id(server->global_list,
4196                                              client_id, TRUE, NULL);
4197     if (!client) {
4198       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4199                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4200                                            0, 2, tmp, tmp_len);
4201       goto out;
4202     }
4203   }
4204
4205   /* Take public key for watching by public key */
4206   pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4207
4208   /* Take nickname */
4209   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4210   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4211   if (!add_nick && !del_nick && !pk) {
4212     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4213                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4214                                           0);
4215     goto out;
4216   }
4217
4218   if (add_nick && add_nick_len > 128) {
4219     add_nick[128] = '\0';
4220     add_nick_len = 128;
4221   }
4222   if (del_nick && del_nick_len > 128) {
4223     del_nick[128] = '\0';
4224     del_nick_len = 128;
4225   }
4226
4227   /* Add new nickname to be watched in our cell */
4228   if (add_nick) {
4229     nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4230                                  &add_nick_len);
4231     if (!nick) {
4232       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4233                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4234       goto out;
4235     }
4236
4237     /* Hash the nick, we have the hash saved, not nicks because we can
4238        do one to one mapping to the nick from Client ID hash this way. */
4239     silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4240
4241     /* Check whether this client is already watching this nickname */
4242     if (silc_hash_table_find_by_context(server->watcher_list, hash,
4243                                         client, NULL)) {
4244       /* Nickname is alredy being watched for this client */
4245       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4246                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
4247                                             0);
4248       silc_free(nick);
4249       goto out;
4250     }
4251
4252     /* Get the nickname from the watcher list and use the same key in
4253        new entries as well.  If key doesn't exist then create it. */
4254     if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4255       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4256
4257     /* Add the client to the watcher list with the specified nickname hash. */
4258     silc_hash_table_add(server->watcher_list, tmp, client);
4259     silc_free(nick);
4260   }
4261
4262   /* Delete nickname from watch list */
4263   if (del_nick) {
4264     nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4265                                  &del_nick_len);
4266     if (!nick) {
4267       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4268                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4269       goto out;
4270     }
4271
4272     /* Hash the nick, we have the hash saved, not nicks because we can
4273        do one to one mapping to the nick from Client ID hash this way. */
4274     silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4275
4276     /* Check that this client is watching for this nickname */
4277     if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4278                                          client, (void *)&tmp)) {
4279       /* Nickname is alredy being watched for this client */
4280       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4281                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4282                                            2, nick, del_nick_len);
4283       silc_free(nick);
4284       goto out;
4285     }
4286
4287     /* Delete the nickname from the watcher list. */
4288     silc_hash_table_del_by_context(server->watcher_list, hash, client);
4289
4290     /* Now check whether there still exists entries with this key, if not
4291        then free the key to not leak memory. */
4292     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4293       silc_free(tmp);
4294     silc_free(nick);
4295   }
4296
4297   /* Add/del public key */
4298   if (pk) {
4299     SilcUInt16 pkargc;
4300     SilcArgumentPayload pkargs;
4301     SilcUInt32 type;
4302     SilcPublicKey public_key, pkkey;
4303
4304     if (pk_len < 2) {
4305       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4306                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4307                                             0);
4308       goto out;
4309     }
4310
4311     /* Get the argument from the Argument List Payload */
4312     SILC_GET16_MSB(pkargc, pk);
4313     pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4314     if (!pkargs) {
4315       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4316                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4317                                             0);
4318       goto out;
4319     }
4320
4321     pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4322     while (pk) {
4323       if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
4324         continue;
4325       if (type == 0x03)
4326         type = 0x00;
4327
4328       if (type == 0x00) {
4329         /* Add public key to watch list */
4330
4331         /* Check whether this client is already watching this public key */
4332         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4333                                             public_key, client, NULL)) {
4334           silc_pkcs_public_key_free(public_key);
4335           silc_server_command_send_status_reply(
4336                                 cmd, SILC_COMMAND_WATCH,
4337                                 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4338           goto out;
4339         }
4340
4341         /* Get the public key from the watcher list and use the same key in
4342            new entries as well.  If key doesn't exist then create it. */
4343         pkkey = NULL;
4344         if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4345                                   (void *)&pkkey, NULL))
4346           pkkey = public_key;
4347         else
4348           silc_pkcs_public_key_free(public_key);
4349
4350         /* Add the client to the watcher list with the specified public
4351            key. */
4352         silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4353
4354       } else if (type == 0x01) {
4355         /* Delete public key from watch list */
4356
4357         /* Check that this client is watching this public key */
4358         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4359                                             public_key, client,
4360                                             (void *)&pkkey)) {
4361           silc_pkcs_public_key_free(public_key);
4362           silc_server_command_send_status_reply(
4363                                 cmd, SILC_COMMAND_WATCH,
4364                                 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4365           goto out;
4366         }
4367
4368         /* Delete the public key from the watcher list. */
4369         silc_hash_table_del_by_context(server->watcher_list_pk,
4370                                        public_key, client);
4371
4372         /* Now check whether there still exists entries with this key, if
4373            not then free the key to not leak memory. */
4374         if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4375           silc_pkcs_public_key_free(pkkey);
4376         silc_pkcs_public_key_free(public_key);
4377       }
4378
4379       pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4380     }
4381   }
4382
4383   /* Send reply */
4384   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4385                                         SILC_STATUS_OK, 0);
4386
4387   /* Distribute the watch list to backup routers too */
4388   if (server->backup) {
4389     SilcBuffer tmpbuf;
4390
4391     /* Statistics */
4392     cmd->server->stat.commands_sent++;
4393
4394     old_ident = silc_command_get_ident(cmd->payload);
4395     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4396     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4397     silc_server_backup_send(server, cmd->sock->user_data, SILC_PACKET_COMMAND,
4398                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
4399                             FALSE, TRUE);
4400     silc_command_set_ident(cmd->payload, old_ident);
4401     silc_buffer_free(tmpbuf);
4402   }
4403
4404  out:
4405   silc_free(client_id);
4406   silc_server_command_free(cmd);
4407 }
4408
4409 /* Server side of SILCOPER command. Client uses this comand to obtain router
4410    operator privileges to this router. */
4411
4412 SILC_SERVER_CMD_FUNC(silcoper)
4413 {
4414   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4415   SilcServer server = cmd->server;
4416   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4417   unsigned char *username = NULL, *auth;
4418   SilcUInt32 tmp_len;
4419   SilcServerConfigAdmin *admin;
4420   SilcIDListData idata = (SilcIDListData)client;
4421   bool result = FALSE;
4422   SilcPublicKey cached_key;
4423
4424   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4425     goto out;
4426
4427   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4428
4429   if (server->server_type != SILC_ROUTER) {
4430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4431                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4432     goto out;
4433   }
4434
4435   /* Get the username */
4436   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4437   if (!username) {
4438     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4439                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4440                                           0);
4441     goto out;
4442   }
4443
4444   /* Check username */
4445   username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4446                                    &tmp_len);
4447   if (!username) {
4448     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4449                                           SILC_STATUS_ERR_BAD_USERNAME,
4450                                           0);
4451     goto out;
4452   }
4453
4454   /* Get the admin configuration */
4455   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4456                                         username, client->nickname);
4457   if (!admin) {
4458     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4459                                           username, client->nickname);
4460     if (!admin) {
4461       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4462                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
4463       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4464                      "nickname '%s' from %s", username,
4465                      client->nickname, cmd->sock->hostname));
4466       goto out;
4467     }
4468   }
4469
4470   /* Get the authentication payload */
4471   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4472   if (!auth) {
4473     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4474                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4475                                           0);
4476     goto out;
4477   }
4478
4479   /* Verify the authentication data. If both passphrase and public key
4480      is set then try both of them. */
4481   if (admin->passphrase)
4482     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4483                                    admin->passphrase, admin->passphrase_len,
4484                                    idata->hash, client->id, SILC_ID_CLIENT);
4485   if (!result && admin->publickeys) {
4486     cached_key = silc_server_get_public_key(server, admin->publickeys);
4487     if (!cached_key)
4488       goto out;
4489     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4490                                    cached_key, 0, idata->hash,
4491                                    client->id, SILC_ID_CLIENT);
4492   }
4493   if (!result) {
4494     /* Authentication failed */
4495     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4496                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4497     goto out;
4498   }
4499
4500   /* Client is now router operator */
4501   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4502
4503   /* Update statistics */
4504   if (SILC_IS_LOCAL(client))
4505     server->stat.my_router_ops++;
4506   if (server->server_type == SILC_ROUTER)
4507     server->stat.router_ops++;
4508
4509   /* Send UMODE change to primary router */
4510   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4511                                 SILC_BROADCAST(server), client->id,
4512                                 client->mode);
4513
4514   /* Check if anyone is watching this nickname */
4515   if (server->server_type == SILC_ROUTER)
4516     silc_server_check_watcher_list(server, client, NULL,
4517                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4518
4519   /* Send reply to the sender */
4520   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4521                                         SILC_STATUS_OK, 0);
4522
4523  out:
4524   silc_free(username);
4525   silc_server_command_free(cmd);
4526 }
4527
4528 /* Server side of command BAN. This is used to manage the ban list of the
4529    channel. To add clients and remove clients from the ban list. */
4530
4531 SILC_SERVER_CMD_FUNC(ban)
4532 {
4533   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4534   SilcServer server = cmd->server;
4535   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4536   SilcBuffer list, tmp2;
4537   SilcChannelEntry channel;
4538   SilcChannelClientEntry chl;
4539   SilcChannelID *channel_id = NULL;
4540   unsigned char *id, *tmp, *atype = NULL;
4541   SilcUInt32 id_len, len, len2;
4542   SilcArgumentPayload args;
4543   SilcHashTableList htl;
4544   SilcUInt32 type;
4545   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4546   SilcBufferStruct blist;
4547
4548   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4549     goto out;
4550
4551   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4552
4553   /* Get Channel ID */
4554   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4555   if (id) {
4556     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4557     if (!channel_id) {
4558       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4559                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4560       goto out;
4561     }
4562   }
4563
4564   /* Get channel entry. The server must know about the channel since the
4565      client is expected to be on the channel. */
4566   channel = silc_idlist_find_channel_by_id(server->local_list,
4567                                            channel_id, NULL);
4568   if (!channel) {
4569     channel = silc_idlist_find_channel_by_id(server->global_list,
4570                                              channel_id, NULL);
4571     if (!channel) {
4572       silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4573                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4574                                            0, 2, id, id_len);
4575       goto out;
4576     }
4577   }
4578
4579   /* Check whether this client is on the channel */
4580   if (!silc_server_client_on_channel(client, channel, &chl)) {
4581     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4582                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4583                                          2, id, id_len);
4584     goto out;
4585   }
4586
4587   /* The client must be at least channel operator. */
4588   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4589     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4590                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4591                                          2, id, id_len);
4592     goto out;
4593   }
4594
4595   /* Get the ban information */
4596   tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4597   if (tmp && len2 > 2) {
4598     /* Parse the arguments to see they are constructed correctly */
4599     SILC_GET16_MSB(argc, tmp);
4600     args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4601     if (!args) {
4602       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4603                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4604                                             0);
4605       goto out;
4606     }
4607
4608     /* Get the type of action */
4609     atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4610     if (atype && len == 1) {
4611       if (atype[0] == 0x00) {
4612         /* Allocate hash table for ban list if it doesn't exist yet */
4613         if (!channel->ban_list)
4614           channel->ban_list =
4615             silc_hash_table_alloc(0, silc_hash_ptr,
4616                                   NULL, NULL, NULL,
4617                                   silc_server_inviteban_destruct, channel,
4618                                   TRUE);
4619
4620         /* Check for resource limit */
4621         if (silc_hash_table_count(channel->ban_list) > 64) {
4622           silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4623                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
4624                                                 0);
4625           goto out;
4626         }
4627       }
4628
4629       /* Now add or delete the information. */
4630       if (!silc_server_inviteban_process(server, channel->ban_list,
4631                                          (SilcUInt8)atype[0], args)) {
4632         silc_server_command_send_status_reply(
4633                                       cmd, SILC_COMMAND_BAN,
4634                                       SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4635                                       0);
4636         goto out;
4637       }
4638     }
4639     silc_argument_payload_free(args);
4640   }
4641
4642   /* Encode ban list */
4643   list = NULL;
4644   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4645     list = silc_buffer_alloc_size(2);
4646     silc_buffer_format(list,
4647                        SILC_STR_UI_SHORT(silc_hash_table_count(
4648                                           channel->ban_list)),
4649                        SILC_STR_END);
4650     silc_hash_table_list(channel->ban_list, &htl);
4651     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4652       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4653                                               type);
4654     silc_hash_table_list_reset(&htl);
4655   }
4656
4657   /* Send BAN notify type to local servers (but not clients) and to
4658      network. */
4659   if (atype && tmp && len2) {
4660     silc_buffer_set(&blist, tmp, len2);
4661
4662     /* Send to local servers if we are router */
4663     if (server->server_type == SILC_ROUTER)
4664       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4665                                          SILC_NOTIFY_TYPE_BAN, 3,
4666                                          id, id_len,
4667                                          atype, 1,
4668                                          tmp ? blist.data : NULL,
4669                                          tmp ? blist.len : 0);
4670
4671     /* Send to network. */
4672     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4673                                 SILC_BROADCAST(server), channel, atype,
4674                                 &blist);
4675   }
4676
4677   /* Send the reply back to the client */
4678   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4679                                  SILC_STATUS_OK, 0, ident, 2,
4680                                  2, id, id_len,
4681                                  3, list ? list->data : NULL,
4682                                  list ? list->len : 0);
4683   silc_buffer_free(list);
4684
4685  out:
4686   silc_free(channel_id);
4687   silc_server_command_free(cmd);
4688 }
4689
4690 /* Server side command of LEAVE. Removes client from a channel. */
4691
4692 SILC_SERVER_CMD_FUNC(leave)
4693 {
4694   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4695   SilcServer server = cmd->server;
4696   SilcSocketConnection sock = cmd->sock;
4697   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4698   SilcChannelID *id = NULL;
4699   SilcChannelEntry channel;
4700   SilcUInt32 len;
4701   unsigned char *tmp;
4702
4703   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4704     goto out;
4705
4706   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4707
4708   /* Get Channel ID */
4709   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4710   if (!tmp) {
4711     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4712                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4713     goto out;
4714   }
4715   id = silc_id_payload_parse_id(tmp, len, NULL);
4716   if (!id) {
4717     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4718                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4719     goto out;
4720   }
4721
4722   /* Get channel entry */
4723   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4724   if (!channel) {
4725     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4726     if (!channel) {
4727       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4728                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4729                                            0, 2, tmp, len);
4730       goto out;
4731     }
4732   }
4733
4734   /* Check whether this client is on the channel */
4735   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4736     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4737                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4738                                          2, tmp, len);
4739     goto out;
4740   }
4741
4742   /* Notify routers that they should remove this client from their list
4743      of clients on the channel. Send LEAVE notify type. */
4744   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4745                                 SILC_BROADCAST(server), channel, id_entry->id);
4746
4747   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4748                                        SILC_STATUS_OK, 0, 2, tmp, len);
4749
4750   /* Remove client from channel */
4751   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4752                                            TRUE))
4753     /* If the channel does not exist anymore we won't send anything */
4754     goto out;
4755
4756   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4757     /* Re-generate channel key */
4758     if (!silc_server_create_channel_key(server, channel, 0))
4759       goto out;
4760
4761     /* Send the channel key */
4762     silc_server_send_channel_key(server, NULL, channel,
4763                                  server->server_type == SILC_ROUTER ?
4764                                  FALSE : !server->standalone);
4765   }
4766
4767  out:
4768   silc_free(id);
4769   silc_server_command_free(cmd);
4770 }
4771
4772 /* Server side of command USERS. Resolves clients and their USERS currently
4773    joined on the requested channel. The list of Client ID's and their modes
4774    on the channel is sent back. */
4775
4776 SILC_SERVER_CMD_FUNC(users)
4777 {
4778   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4779   SilcServer server = cmd->server;
4780   SilcChannelEntry channel;
4781   SilcChannelID *id = NULL;
4782   SilcBuffer idp;
4783   unsigned char *channel_id;
4784   SilcUInt32 channel_id_len;
4785   SilcBuffer client_id_list;
4786   SilcBuffer client_mode_list;
4787   unsigned char lc[4];
4788   SilcUInt32 list_count = 0;
4789   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4790   char *channel_name, *channel_namec = NULL;
4791
4792   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4793
4794   /* Get Channel ID */
4795   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4796
4797   /* Get channel name */
4798   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4799
4800   if (!channel_id && !channel_name) {
4801     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4802                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4803     goto out;
4804   }
4805
4806   /* Check channel name */
4807   if (channel_name) {
4808     channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4809                                             SILC_STRING_UTF8, 256, NULL);
4810     if (!channel_namec) {
4811       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4812                                             SILC_STATUS_ERR_BAD_CHANNEL, 0);
4813       goto out;
4814     }
4815   }
4816
4817   /* Check Channel ID */
4818   if (channel_id) {
4819     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4820     if (!id) {
4821       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4822                                            SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4823                                            2, channel_id, channel_id_len);
4824       goto out;
4825     }
4826   }
4827
4828   /* If we are server and we don't know about this channel we will send
4829      the command to our router. If we know about the channel then we also
4830      have the list of users already. */
4831   if (id)
4832     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4833   else
4834     channel = silc_idlist_find_channel_by_name(server->local_list,
4835                                                channel_namec, NULL);
4836
4837   if (!channel || (!server->standalone && (channel->disabled ||
4838                     !channel->users_resolved))) {
4839     if (server->server_type != SILC_ROUTER && !server->standalone &&
4840         !cmd->pending) {
4841       SilcBuffer tmpbuf;
4842
4843       /* Statistics */
4844       cmd->server->stat.commands_sent++;
4845
4846       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4847       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4848
4849       /* Send USERS command */
4850       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4851                               SILC_PACKET_COMMAND, cmd->packet->flags,
4852                               tmpbuf->data, tmpbuf->len, TRUE);
4853
4854       /* Reprocess this packet after received reply */
4855       silc_server_command_pending(server, SILC_COMMAND_USERS,
4856                                   silc_command_get_ident(cmd->payload),
4857                                   silc_server_command_users,
4858                                   silc_server_command_dup(cmd));
4859       cmd->pending = TRUE;
4860       silc_command_set_ident(cmd->payload, ident);
4861       silc_buffer_free(tmpbuf);
4862       silc_free(id);
4863       goto out;
4864     }
4865
4866     /* Check the global list as well. */
4867     if (id)
4868       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4869     else
4870       channel = silc_idlist_find_channel_by_name(server->global_list,
4871                                                  channel_namec, NULL);
4872     if (!channel) {
4873       /* Channel really does not exist */
4874       if (id)
4875         silc_server_command_send_status_data(
4876                                     cmd, SILC_COMMAND_USERS,
4877                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4878                                     2, channel_id, channel_id_len);
4879       else
4880         silc_server_command_send_status_data(
4881                                     cmd, SILC_COMMAND_USERS,
4882                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4883                                     2, channel_name, strlen(channel_name));
4884       goto out;
4885     }
4886   }
4887
4888   /* If the channel is private or secret do not send anything, unless the
4889      user requesting this command is on the channel or is server */
4890   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4891     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4892         && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4893                                           NULL)) {
4894       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4895                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4896                                            2, channel->channel_name,
4897                                            strlen(channel->channel_name));
4898       goto out;
4899     }
4900   }
4901
4902   /* Get the users list */
4903   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4904                                         &client_mode_list, &list_count)) {
4905     list_count = 0;
4906     client_id_list = NULL;
4907     client_mode_list = NULL;
4908   }
4909
4910   /* List count */
4911   SILC_PUT32_MSB(list_count, lc);
4912
4913   /* Send reply */
4914   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4915   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
4916                                  SILC_STATUS_OK, 0, ident, 4,
4917                                  2, idp->data, idp->len,
4918                                  3, lc, 4,
4919                                  4, client_id_list ?
4920                                  client_id_list->data : NULL,
4921                                  client_id_list ?
4922                                  client_id_list->len : 0,
4923                                  5, client_mode_list ?
4924                                  client_mode_list->data : NULL,
4925                                  client_mode_list ?
4926                                  client_mode_list->len : 0);
4927   silc_buffer_free(idp);
4928   if (client_id_list)
4929     silc_buffer_free(client_id_list);
4930   if (client_mode_list)
4931     silc_buffer_free(client_mode_list);
4932   silc_free(id);
4933
4934  out:
4935   silc_free(channel_namec);
4936   silc_server_command_free(cmd);
4937 }
4938
4939 /* Server side of command GETKEY. This fetches the client's public key
4940    from the server where to the client is connected. */
4941
4942 SILC_SERVER_CMD_FUNC(getkey)
4943 {
4944   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4945   SilcServer server = cmd->server;
4946   SilcClientEntry client;
4947   SilcServerEntry server_entry;
4948   SilcClientID *client_id = NULL;
4949   SilcServerID *server_id = NULL;
4950   SilcIDPayload idp = NULL;
4951   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4952   unsigned char *tmp;
4953   SilcUInt32 tmp_len;
4954   SilcBuffer pk = NULL;
4955   SilcIdType id_type;
4956   SilcPublicKey public_key;
4957
4958   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4959   if (!tmp) {
4960     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4961                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4962                                           0);
4963     goto out;
4964   }
4965   idp = silc_id_payload_parse(tmp, tmp_len);
4966   if (!idp) {
4967     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4968                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4969                                           0);
4970     goto out;
4971   }
4972
4973   id_type = silc_id_payload_get_type(idp);
4974   if (id_type == SILC_ID_CLIENT) {
4975     client_id = silc_id_payload_get_id(idp);
4976
4977     /* If the client is not found from local list there is no chance it
4978        would be locally connected client so send the command further. */
4979     client = silc_idlist_find_client_by_id(server->local_list,
4980                                            client_id, TRUE, NULL);
4981     if (!client)
4982       client = silc_idlist_find_client_by_id(server->global_list,
4983                                              client_id, TRUE, NULL);
4984
4985     if ((!client && !cmd->pending && !server->standalone) ||
4986         (client && !client->connection && !cmd->pending &&
4987          !(client->mode & SILC_UMODE_DETACHED)) ||
4988         (client && !client->data.public_key && !cmd->pending)) {
4989       SilcBuffer tmpbuf;
4990       SilcUInt16 old_ident;
4991       SilcSocketConnection dest_sock;
4992
4993       dest_sock = silc_server_get_client_route(server, NULL, 0,
4994                                                client_id, NULL, NULL);
4995       if (!dest_sock)
4996         goto out;
4997
4998       /* Statistics */
4999       cmd->server->stat.commands_sent++;
5000
5001       old_ident = silc_command_get_ident(cmd->payload);
5002       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5003       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5004
5005       silc_server_packet_send(server, dest_sock,
5006                               SILC_PACKET_COMMAND, cmd->packet->flags,
5007                               tmpbuf->data, tmpbuf->len, TRUE);
5008
5009       /* Reprocess this packet after received reply from router */
5010       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5011                                   silc_command_get_ident(cmd->payload),
5012                                   silc_server_command_getkey,
5013                                   silc_server_command_dup(cmd));
5014       cmd->pending = TRUE;
5015       silc_command_set_ident(cmd->payload, old_ident);
5016       silc_buffer_free(tmpbuf);
5017       goto out;
5018     }
5019
5020     if (!client) {
5021       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5022                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5023                                            0, 2, tmp, tmp_len);
5024       goto out;
5025     }
5026
5027     /* The client is locally connected, just get the public key and
5028        send it back. If they key does not exist then do not send it,
5029        send just OK reply */
5030     public_key = client->data.public_key;
5031     if (public_key)
5032       pk = silc_pkcs_public_key_payload_encode(public_key);
5033   } else if (id_type == SILC_ID_SERVER) {
5034     server_id = silc_id_payload_get_id(idp);
5035
5036     /* If the server is not found from local list there is no chance it
5037        would be locally connected server so send the command further. */
5038     server_entry = silc_idlist_find_server_by_id(server->local_list,
5039                                                  server_id, TRUE, NULL);
5040     if (!server_entry)
5041       server_entry = silc_idlist_find_server_by_id(server->global_list,
5042                                                    server_id, TRUE, NULL);
5043
5044     if (server_entry != server->id_entry &&
5045         ((!server_entry && !cmd->pending && !server->standalone) ||
5046          (server_entry && !server_entry->connection && !cmd->pending &&
5047           !server->standalone) ||
5048          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5049           !server->standalone))) {
5050       SilcBuffer tmpbuf;
5051       SilcUInt16 old_ident;
5052
5053       /* Statistics */
5054       cmd->server->stat.commands_sent++;
5055
5056       old_ident = silc_command_get_ident(cmd->payload);
5057       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5058       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5059
5060       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5061                               SILC_PACKET_COMMAND, cmd->packet->flags,
5062                               tmpbuf->data, tmpbuf->len, TRUE);
5063
5064       /* Reprocess this packet after received reply from router */
5065       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5066                                   silc_command_get_ident(cmd->payload),
5067                                   silc_server_command_getkey,
5068                                   silc_server_command_dup(cmd));
5069       cmd->pending = TRUE;
5070       silc_command_set_ident(cmd->payload, old_ident);
5071       silc_buffer_free(tmpbuf);
5072       goto out;
5073     }
5074
5075     if (!server_entry) {
5076       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5077                                            SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5078                                            0, 2, tmp, tmp_len);
5079       goto out;
5080     }
5081
5082     /* If they key does not exist then do not send it, send just OK reply */
5083     public_key = (!server_entry->data.public_key ?
5084                   (server_entry == server->id_entry ? server->public_key :
5085                    NULL) : server_entry->data.public_key);
5086     if (public_key)
5087       pk = silc_pkcs_public_key_payload_encode(public_key);
5088   } else {
5089     goto out;
5090   }
5091
5092   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5093   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5094                                  SILC_STATUS_OK, 0, ident, 2,
5095                                  2, tmp, tmp_len,
5096                                  3, pk ? pk->data : NULL,
5097                                  pk ? pk->len : 0);
5098
5099  out:
5100   if (idp)
5101     silc_id_payload_free(idp);
5102   silc_buffer_free(pk);
5103   silc_free(client_id);
5104   silc_free(server_id);
5105   silc_server_command_free(cmd);
5106 }
5107
5108 /* Server side of command SERVICE. */
5109 /* XXX currently this just sends empty reply back */
5110
5111 SILC_SERVER_CMD_FUNC(service)
5112 {
5113   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5114   SilcServer server = cmd->server;
5115   SilcUInt32 tmp_len, auth_len;
5116   unsigned char *service_name, *auth;
5117   bool send_list = FALSE;
5118   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5119
5120   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5121
5122   /* Get requested service */
5123   service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5124   if (service_name && tmp_len) {
5125     /* Verify service name */
5126     if (!silc_identifier_verify(service_name, tmp_len,
5127                                 SILC_STRING_UTF8, 256)) {
5128       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5129                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5130                                             0);
5131       goto out;
5132     }
5133   }
5134
5135   /* Get authentication payload if present */
5136   auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5137   if (auth) {
5138     /* XXX */
5139   }
5140
5141
5142   send_list = TRUE;
5143
5144   /* Send our service list back */
5145   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5146                                  SILC_STATUS_OK, 0, ident, 0);
5147
5148  out:
5149   silc_server_command_free(cmd);
5150 }
5151
5152
5153 /* Private range commands, specific to this implementation */
5154
5155 /* Server side command of CONNECT. Connects us to the specified remote
5156    server or router. */
5157
5158 SILC_SERVER_CMD_FUNC(connect)
5159 {
5160   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5161   SilcServer server = cmd->server;
5162   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5163   unsigned char *tmp, *host;
5164   SilcUInt32 tmp_len;
5165   SilcUInt32 port = SILC_PORT;
5166
5167   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5168     goto out;
5169
5170   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5171
5172   /* Check whether client has the permissions. */
5173   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5174       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5175     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5176                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5177     goto out;
5178   }
5179
5180   if (server->server_type == SILC_ROUTER && !server->backup_router &&
5181       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5182     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5183                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5184     goto out;
5185   }
5186
5187   /* Get the remote server */
5188   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5189   if (!host) {
5190     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5191                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5192                                           0);
5193     goto out;
5194   }
5195
5196   /* Get port */
5197   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5198   if (tmp)
5199     SILC_GET32_MSB(port, tmp);
5200
5201   /* Create the connection. It is done with timeout and is async. */
5202   silc_server_create_connection(server, host, port);
5203
5204   /* Send reply to the sender */
5205   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5206                                         SILC_STATUS_OK, 0);
5207
5208  out:
5209   silc_server_command_free(cmd);
5210 }
5211
5212 /* Server side command of CLOSE. Closes connection to a specified server. */
5213
5214 SILC_SERVER_CMD_FUNC(close)
5215 {
5216   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5217   SilcServer server = cmd->server;
5218   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5219   SilcServerEntry server_entry;
5220   SilcSocketConnection sock;
5221   unsigned char *tmp;
5222   SilcUInt32 tmp_len;
5223   unsigned char *name;
5224   SilcUInt32 port = SILC_PORT;
5225
5226   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5227     goto out;
5228
5229   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5230
5231   /* Check whether client has the permissions. */
5232   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5233       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5234     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5235                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5236                                           0);
5237     goto out;
5238   }
5239
5240   /* Get the remote server */
5241   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5242   if (!name) {
5243     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5244                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5245                                           0);
5246     goto out;
5247   }
5248
5249   /* Get port */
5250   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5251   if (tmp)
5252     SILC_GET32_MSB(port, tmp);
5253
5254   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5255                                                  name, port, TRUE, NULL);
5256   if (!server_entry)
5257     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5258                                                    name, port, TRUE, NULL);
5259   if (!server_entry) {
5260     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5261                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5262     goto out;
5263   }
5264
5265   if (server_entry == server->id_entry) {
5266     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5267                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5268     goto out;
5269   }
5270
5271   /* Send reply to the sender */
5272   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5273                                         SILC_STATUS_OK, 0);
5274
5275   /* Close the connection to the server */
5276   sock = (SilcSocketConnection)server_entry->connection;
5277
5278   if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5279     server->backup_closed = TRUE;
5280     silc_server_backup_del(server, server_entry);
5281   }
5282
5283   server->backup_noswitch = TRUE;
5284   if (server->router == server_entry) {
5285     server->id_entry->router = NULL;
5286     server->router = NULL;
5287     server->standalone = TRUE;
5288   }
5289   silc_server_disconnect_remote(server, sock,
5290                                 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5291                                 "Closed by administrator");
5292   if (sock->user_data)
5293     silc_server_free_sock_user_data(server, sock, NULL);
5294   server->backup_noswitch = FALSE;
5295
5296  out:
5297   silc_server_command_free(cmd);
5298 }
5299
5300 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5301    active connections. */
5302
5303 SILC_SERVER_CMD_FUNC(shutdown)
5304 {
5305   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5306   SilcServer server = cmd->server;
5307   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5308
5309   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5310     goto out;
5311
5312   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5313
5314   /* Check whether client has the permission. */
5315   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5316       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5317     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5318                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5319                                           0);
5320     goto out;
5321   }
5322
5323   /* Send reply to the sender */
5324   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5325                                         SILC_STATUS_OK, 0);
5326
5327   /* Then, gracefully, or not, bring the server down. */
5328   silc_server_stop(server);
5329   exit(0);
5330
5331  out:
5332   silc_server_command_free(cmd);
5333 }