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