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