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