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