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