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