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