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