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