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