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