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