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