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