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