Added missing memset's for sensitive data.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12   
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 static int silc_server_is_registered(SilcServer server,
25                                      SilcSocketConnection sock,
26                                      SilcServerCommandContext cmd,
27                                      SilcCommand command);
28 static void 
29 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
30                                       SilcCommand command,
31                                       SilcStatus status,
32                                       SilcStatus error);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcStatus status,
37                                      SilcStatus error,
38                                      SilcUInt32 arg_type,
39                                      const unsigned char *arg,
40                                      SilcUInt32 arg_len);
41 static bool
42 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
43                                         SilcServerCommandReplyContext cmdr,
44                                         SilcCommand command);
45 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46
47 /* Server command list. */
48 SilcServerCommand silc_command_list[] =
49 {
50   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
54   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
55   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
56   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
60   SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
71   SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
72   SILC_SERVER_CMD(silcoper, SILCOPER,
73                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
74   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
75   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
76   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
77
78   SILC_SERVER_CMD(connect, PRIV_CONNECT, 
79                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80   SILC_SERVER_CMD(close, PRIV_CLOSE,
81                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
82   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
83                   SILC_CF_OPER),
84
85   { NULL, 0 },
86 };
87
88 /* Performs several checks to the command. It first checks whether this
89    command was called as pending command callback. If it was then it checks
90    whether error occurred in the command reply where the pending command
91    callback was called. 
92
93    It also checks that the requested command includes correct amount
94    of arguments. */
95 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                \
96 do {                                                                         \
97   SilcUInt32 _argc;                                                          \
98                                                                              \
99   if (silc_server_command_pending_error_check(cmd, context2, command)) {     \
100     SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
101     silc_server_command_free(cmd);                                           \
102     return;                                                                  \
103   }                                                                          \
104                                                                              \
105   _argc = silc_argument_get_arg_num(cmd->args);                              \
106   if (_argc < min) {                                                         \
107     SILC_LOG_DEBUG(("Not enough parameters in command"));                    \
108     silc_server_command_send_status_reply(cmd, command,                      \
109                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
110                                           0);                                \
111     silc_server_command_free(cmd);                                           \
112     return;                                                                  \
113   }                                                                          \
114   if (_argc > max) {                                                         \
115     SILC_LOG_DEBUG(("Too many parameters in command"));                      \
116     silc_server_command_send_status_reply(cmd, command,                      \
117                                           SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
118                                           0);                                \
119     silc_server_command_free(cmd);                                           \
120     return;                                                                  \
121   }                                                                          \
122 } while(0)
123
124 /* Returns TRUE if the connection is registered. Unregistered connections
125    usually cannot send commands hence the check. */
126
127 static int silc_server_is_registered(SilcServer server,
128                                      SilcSocketConnection sock,
129                                      SilcServerCommandContext cmd,
130                                      SilcCommand command)
131 {
132   SilcIDListData idata = (SilcIDListData)sock->user_data;
133
134   if (!idata)
135     return FALSE;
136
137   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
138     return TRUE;
139
140   silc_server_command_send_status_reply(cmd, command,
141                                         SILC_STATUS_ERR_NOT_REGISTERED, 0);
142   return FALSE;
143 }
144
145 /* Internal context to hold data when executed command with timeout. */
146 typedef struct {
147   SilcServerCommandContext ctx;
148   SilcServerCommand *cmd;
149 } *SilcServerCommandTimeout;
150
151 /* Timeout callback to process commands with timeout for client. Client's
152    commands are always executed with timeout. */
153
154 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
155 {
156   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
157   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
158
159   if (!client) {
160     SILC_LOG_DEBUG(("Client entry is invalid"));
161     silc_server_command_free(timeout->ctx);
162     silc_free(timeout);
163     return;
164   }
165
166   /* Update access time */
167   client->last_command = time(NULL);
168
169   if (!(timeout->cmd->flags & SILC_CF_REG)) {
170     SILC_LOG_DEBUG(("Calling %s command",
171                     silc_get_command_name(timeout->cmd->cmd)));
172     timeout->cmd->cb(timeout->ctx, NULL);
173   } else if (silc_server_is_registered(timeout->ctx->server, 
174                                        timeout->ctx->sock, 
175                                        timeout->ctx, 
176                                        timeout->cmd->cmd)) {
177     SILC_LOG_DEBUG(("Calling %s command",
178                     silc_get_command_name(timeout->cmd->cmd)));
179     timeout->cmd->cb(timeout->ctx, NULL);
180   } else {
181     SILC_LOG_DEBUG(("Client is not registered"));
182     silc_server_command_free(timeout->ctx);
183   }
184
185   silc_free(timeout);
186 }
187
188 /* Processes received command packet. */
189
190 void silc_server_command_process(SilcServer server,
191                                  SilcSocketConnection sock,
192                                  SilcPacketContext *packet)
193 {
194   SilcServerCommandContext ctx;
195   SilcServerCommand *cmd;
196   SilcCommand command;
197
198   /* Allocate command context. This must be free'd by the
199      command routine receiving it. */
200   ctx = silc_server_command_alloc();
201   ctx->server = server;
202   ctx->sock = silc_socket_dup(sock);
203   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
204   
205   /* Parse the command payload in the packet */
206   ctx->payload = silc_command_payload_parse(packet->buffer->data,
207                                             packet->buffer->len);
208   if (!ctx->payload) {
209     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210     silc_packet_context_free(packet);
211     silc_socket_free(ctx->sock);
212     silc_free(ctx);
213     return;
214   }
215   ctx->args = silc_command_get_args(ctx->payload);
216
217   /* Get the command */
218   command = silc_command_get(ctx->payload);
219   for (cmd = silc_command_list; cmd->cb; cmd++)
220     if (cmd->cmd == command)
221       break;
222
223   if (!cmd || !cmd->cb) {
224     SILC_LOG_DEBUG(("Unknown command %d", command));
225     silc_server_command_send_status_reply(ctx, command,
226                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227     silc_server_command_free(ctx);
228     return;
229   }
230
231   /* Execute client's commands always with timeout.  Normally they are
232      executed with zero (0) timeout but if client is sending command more
233      frequently than once in 2 seconds, then the timeout may be 0 to 2
234      seconds. */
235   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236     SilcClientEntry client = (SilcClientEntry)sock->user_data;
237     SilcServerCommandTimeout timeout;
238     int fast;
239
240     if (!client) {
241       SILC_LOG_DEBUG(("Client entry is invalid"));
242       silc_server_command_free(ctx);
243       return;
244     }
245
246     timeout = silc_calloc(1, sizeof(*timeout));
247     timeout->ctx = ctx;
248     timeout->cmd = cmd;
249
250     if (client->last_command && (time(NULL) - client->last_command) < 2) {
251       client->fast_command++;
252       fast = FALSE;
253     } else {
254       if (client->fast_command - 2 <= 0)
255         client->fast_command = 0;
256       else
257         client->fast_command -= 2;
258       fast = TRUE;
259     }
260
261     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
262                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
263       silc_schedule_task_add(server->schedule, sock->sock, 
264                              silc_server_command_process_timeout, timeout,
265                              (client->fast_command < 3 ? 0 :
266                               2 - (time(NULL) - client->last_command)),
267                              (client->fast_command < 3 ? 200000 : 0),
268                              SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
269     else
270       silc_schedule_task_add(server->schedule, sock->sock, 
271                              silc_server_command_process_timeout, timeout,
272                              0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
273     return;
274   }
275
276   /* Execute for server */
277
278   if (!(cmd->flags & SILC_CF_REG)) {
279     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
280     cmd->cb(ctx, NULL);
281   } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
282     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
283     cmd->cb(ctx, NULL);
284   } else {
285     SILC_LOG_DEBUG(("Server is not registered"));
286     silc_server_command_free(ctx);
287   }
288 }
289
290 /* Allocate Command Context */
291
292 SilcServerCommandContext silc_server_command_alloc()
293 {
294   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
295   ctx->users++;
296   return ctx;
297 }
298
299 /* Free's the command context allocated before executing the command */
300
301 void silc_server_command_free(SilcServerCommandContext ctx)
302 {
303   ctx->users--;
304   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
305                   ctx->users));
306   if (ctx->users < 1) {
307     if (ctx->payload)
308       silc_command_payload_free(ctx->payload);
309     if (ctx->packet)
310       silc_packet_context_free(ctx->packet);
311     if (ctx->sock)
312       silc_socket_free(ctx->sock); /* Decrease reference counter */
313     silc_free(ctx);
314   }
315 }
316
317 /* Duplicate Command Context by adding reference counter. The context won't
318    be free'd untill it hits zero. */
319
320 SilcServerCommandContext 
321 silc_server_command_dup(SilcServerCommandContext ctx)
322 {
323   ctx->users++;
324   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
325                   ctx->users));
326   return ctx;
327 }
328
329 /* Timeout for pending command.  If reply to pending command never arrives
330    this is called to free resources. */
331
332 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
333 {
334   SilcServer server = app_context;
335   SilcServerCommandPending *reply = context;
336   SilcServerCommandReplyContext cmdr;
337   SilcBuffer tmpreply;
338   int i;
339
340   SILC_LOG_DEBUG(("Timeout pending command"));
341
342   /* Allocate temporary and bogus command reply context */
343   cmdr = silc_calloc(1, sizeof(*cmdr));
344   cmdr->server = server;
345   cmdr->ident = reply->ident;
346       
347   /* Check for pending commands and mark to be exeucted */
348   cmdr->callbacks = 
349     silc_server_command_pending_check(server, reply->reply_cmd,
350                                       reply->ident, &cmdr->callbacks_count);
351
352   /* Create bogus command reply with an error inside */
353   tmpreply =
354     silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
355                                          SILC_COMMAND_RESERVED,
356                                          SILC_STATUS_ERR_TIMEDOUT, 0,
357                                          reply->ident, 0);
358   cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
359   silc_buffer_free(tmpreply);
360
361   /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
362   for (i = 0; i < cmdr->callbacks_count; i++)
363     if (cmdr->callbacks[i].callback)
364       (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
365
366   silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
367   silc_server_command_reply_free(cmdr);
368 }
369
370 /* Add new pending command to be executed when reply to a command has been
371    received. The `reply_cmd' is the command that will call the `callback'
372    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
373    to match any command with the `ident'.  If `ident' is non-zero
374    the `callback' will be executed when received reply with command
375    identifier `ident'. If there already exists pending command for the
376    specified command, ident, callback and context this function has no
377    effect. */
378
379 bool silc_server_command_pending(SilcServer server,
380                                  SilcCommand reply_cmd,
381                                  SilcUInt16 ident,
382                                  SilcCommandCb callback,
383                                  void *context)
384 {
385   return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
386                                            context, 0);
387 }
388
389 /* Same as silc_server_command_pending with specific timeout for pending
390    commands.  If the `timeout' is zero default timeout is used. */
391
392 bool silc_server_command_pending_timed(SilcServer server,
393                                        SilcCommand reply_cmd,
394                                        SilcUInt16 ident,
395                                        SilcCommandCb callback,
396                                        void *context,
397                                        SilcUInt16 timeout)
398 {
399   SilcServerCommandPending *reply;
400
401   /* Check whether identical pending already exists for same command,
402      ident, callback and callback context. If it does then it would be
403      error to register it again. */
404   silc_dlist_start(server->pending_commands);
405   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
406     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
407         reply->callback == callback && reply->context == context)
408       return FALSE;
409   }
410
411   reply = silc_calloc(1, sizeof(*reply));
412   reply->reply_cmd = reply_cmd;
413   reply->ident = ident;
414   reply->context = context;
415   reply->callback = callback;
416   reply->timeout =
417     silc_schedule_task_add(server->schedule, 0,
418                            silc_server_command_pending_timeout, reply,
419                            timeout ? timeout : 10, 0,
420                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
421   silc_dlist_add(server->pending_commands, reply);
422
423   return TRUE;
424 }
425
426 /* Deletes pending command by reply command type. */
427
428 void silc_server_command_pending_del(SilcServer server,
429                                      SilcCommand reply_cmd,
430                                      SilcUInt16 ident)
431 {
432   SilcServerCommandPending *r;
433
434   silc_dlist_start(server->pending_commands);
435   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
436     if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
437                                        r->reply_check))
438         && r->ident == ident) {
439       silc_dlist_del(server->pending_commands, r);
440       if (r->timeout)
441         silc_schedule_task_del(server->schedule, r->timeout);
442       silc_free(r);
443     }
444   }
445 }
446
447 /* Checks for pending commands and marks callbacks to be called from
448    the command reply function. Returns TRUE if there were pending command. */
449
450 SilcServerCommandPendingCallbacks
451 silc_server_command_pending_check(SilcServer server,
452                                   SilcCommand command, 
453                                   SilcUInt16 ident,
454                                   SilcUInt32 *callbacks_count)
455 {
456   SilcServerCommandPending *r;
457   SilcServerCommandPendingCallbacks callbacks = NULL;
458   int i = 0;
459
460   silc_dlist_start(server->pending_commands);
461   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
462     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
463         && r->ident == ident) {
464       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
465       callbacks[i].context = r->context;
466       callbacks[i].callback = r->callback;
467       r->reply_check = TRUE;
468       i++;
469     }
470   }
471
472   *callbacks_count = i;
473   return callbacks;
474 }
475
476 /* Sends simple status message as command reply packet */
477
478 static void 
479 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
480                                       SilcCommand command,
481                                       SilcStatus status,
482                                       SilcStatus error)
483 {
484   SilcBuffer buffer;
485
486   SILC_LOG_DEBUG(("Sending command status %d", status));
487
488   buffer = 
489     silc_command_reply_payload_encode_va(command, status, error,
490                                          silc_command_get_ident(cmd->payload),
491                                          0);
492   silc_server_packet_send(cmd->server, cmd->sock,
493                           SILC_PACKET_COMMAND_REPLY, 0, 
494                           buffer->data, buffer->len, FALSE);
495   silc_buffer_free(buffer);
496 }
497
498 /* Sends command status reply with one extra argument. The argument
499    type must be sent as argument. */
500
501 static void 
502 silc_server_command_send_status_data(SilcServerCommandContext cmd,
503                                      SilcCommand command,
504                                      SilcStatus status,
505                                      SilcStatus error,
506                                      SilcUInt32 arg_type,
507                                      const unsigned char *arg,
508                                      SilcUInt32 arg_len)
509 {
510   SilcBuffer buffer;
511
512   SILC_LOG_DEBUG(("Sending command status %d", status));
513
514   buffer = 
515     silc_command_reply_payload_encode_va(command, status, 0,
516                                          silc_command_get_ident(cmd->payload),
517                                          1, arg_type, arg, arg_len);
518   silc_server_packet_send(cmd->server, cmd->sock,
519                           SILC_PACKET_COMMAND_REPLY, 0, 
520                           buffer->data, buffer->len, FALSE);
521   silc_buffer_free(buffer);
522 }
523
524 /* This function can be called to check whether in the command reply
525    an error occurred. This function has no effect if this is called
526    when the command function was not called as pending command callback. 
527    This returns TRUE if error had occurred. */
528
529 static bool
530 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
531                                         SilcServerCommandReplyContext cmdr,
532                                         SilcCommand command)
533 {
534   if (!cmd->pending || !cmdr)
535     return FALSE;
536
537   if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
538     SilcBuffer buffer;
539
540     /* Send the same command reply payload */
541     silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
542     silc_command_set_ident(cmdr->payload, 
543                            silc_command_get_ident(cmd->payload));
544     buffer = silc_command_payload_encode_payload(cmdr->payload);
545     silc_server_packet_send(cmd->server, cmd->sock,
546                             SILC_PACKET_COMMAND_REPLY, 0, 
547                             buffer->data, buffer->len, FALSE);
548     silc_buffer_free(buffer);
549     return TRUE;
550   }
551
552   return FALSE;
553 }
554
555 /* Server side of command WHOIS. */
556
557 SILC_SERVER_CMD_FUNC(whois)
558 {
559   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
560   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
561   silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
562   silc_server_command_free(cmd);
563 }
564
565 /* Server side of command WHOWAS. */
566
567 SILC_SERVER_CMD_FUNC(whowas)
568 {
569   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
570   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
571   silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
572   silc_server_command_free(cmd);
573 }
574
575 /* Server side of command IDENTIFY. */
576
577 SILC_SERVER_CMD_FUNC(identify)
578 {
579   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
580   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
581   silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
582   silc_server_command_free(cmd);
583 }
584
585 /* Server side of command NICK. Sets nickname for user. Setting
586    nickname causes generation of a new client ID for the client. The
587    new client ID is sent to the client after changing the nickname. */
588
589 SILC_SERVER_CMD_FUNC(nick)
590 {
591   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
592   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
593   SilcServer server = cmd->server;
594   SilcBuffer packet, nidp, oidp = NULL;
595   SilcClientID *new_id;
596   SilcUInt32 nick_len;
597   char *nick;
598   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
599   int nickfail = 0;
600
601   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
602     goto out;
603
604   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
605
606   /* Check nickname */
607   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
608   if (!nick) {
609     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
610                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
611     goto out;
612   }
613   if (nick_len > 128)
614     nick[128] = '\0';
615   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
616     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
617                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
618     goto out;
619   }
620
621   /* Check for same nickname */
622   if (!strcmp(client->nickname, nick)) {
623     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
624     goto send_reply;
625   }
626
627   /* Create new Client ID */
628   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
629                                    cmd->server->rng, 
630                                    cmd->server->md5hash, nick,
631                                    &new_id)) {
632     nickfail++;
633     if (nickfail > 9) {
634       silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
635                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
636       goto out;
637     }
638     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
639   }
640
641   /* Send notify about nickname change to our router. We send the new
642      ID and ask to replace it with the old one. If we are router the
643      packet is broadcasted. Send NICK_CHANGE notify. */
644   silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
645                                       SILC_BROADCAST(server), client->id,
646                                       new_id, nick);
647
648   /* Check if anyone is watching the old nickname */
649   if (server->server_type == SILC_ROUTER)
650     silc_server_check_watcher_list(server, client, nick,
651                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
652
653   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
654
655   /* Remove old cache entry */
656   silc_idcache_del_by_context(server->local_list->clients, client);
657
658   silc_free(client->id);
659   client->id = new_id;
660
661   silc_free(client->nickname);
662   client->nickname = strdup(nick);
663
664   /* Update client cache */
665   silc_idcache_add(server->local_list->clients, client->nickname, 
666                    client->id, (void *)client, 0, NULL);
667
668   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
669
670   /* Send NICK_CHANGE notify to the client's channels */
671   silc_server_send_notify_on_channels(server, NULL, client, 
672                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
673                                       oidp->data, oidp->len, 
674                                       nidp->data, nidp->len,
675                                       client->nickname, 
676                                       strlen(client->nickname));
677
678   /* Check if anyone is watching the new nickname */
679   if (server->server_type == SILC_ROUTER)
680     silc_server_check_watcher_list(server, client, NULL,
681                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
682
683  send_reply:
684   /* Send the new Client ID as reply command back to client */
685   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
686                                                 SILC_STATUS_OK, 0, ident, 2,
687                                                 2, nidp->data, nidp->len,
688                                                 3, nick, strlen(nick));
689   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
690                           0, packet->data, packet->len, FALSE);
691
692   silc_buffer_free(packet);
693   silc_buffer_free(nidp);
694   if (oidp)
695     silc_buffer_free(oidp);
696   
697  out:
698   silc_server_command_free(cmd);
699 }
700
701 /* Sends the LIST command reply */
702
703 static void
704 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
705                                     SilcChannelEntry *lch, 
706                                     SilcUInt32 lch_count,
707                                     SilcChannelEntry *gch,
708                                     SilcUInt32 gch_count)
709 {
710   int i, k;
711   SilcBuffer packet, idp;
712   SilcChannelEntry entry;
713   SilcStatus status;
714   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
715   char *topic;
716   unsigned char usercount[4];
717   SilcUInt32 users;
718   int valid_lcount = 0, valid_rcount = 0;
719
720   for (i = 0; i < lch_count; i++) {
721     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
722       lch[i] = NULL;
723     else
724       valid_lcount++;
725   }
726   for (i = 0; i < gch_count; i++) {
727     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
728       gch[i] = NULL;
729     else
730       valid_rcount++;
731   }
732
733   status = SILC_STATUS_OK;
734   if ((lch_count + gch_count) > 1)
735     status = SILC_STATUS_LIST_START;
736
737   /* Local list */
738   for (i = 0, k = 0; i < lch_count; i++) {
739     entry = lch[i];
740     if (!entry)
741       continue;
742
743     if (k >= 1)
744       status = SILC_STATUS_LIST_ITEM;
745     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
746       status = SILC_STATUS_LIST_END;
747
748     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
749
750     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
751       topic = "*private*";
752       memset(usercount, 0, sizeof(usercount));
753     } else {
754       topic = entry->topic;
755       users = silc_hash_table_count(entry->user_list);
756       SILC_PUT32_MSB(users, usercount);
757     }
758
759     /* Send the reply */
760     packet = 
761       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
762                                            status, 0, ident, 4,
763                                            2, idp->data, idp->len,
764                                            3, entry->channel_name, 
765                                            strlen(entry->channel_name),
766                                            4, topic, topic ? strlen(topic) : 0,
767                                            5, usercount, 4);
768     silc_server_packet_send(cmd->server, cmd->sock, 
769                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
770                             packet->len, FALSE);
771     silc_buffer_free(packet);
772     silc_buffer_free(idp);
773     k++;
774   }
775
776   /* Global list */
777   for (i = 0, k = 0; i < gch_count; i++) {
778     entry = gch[i];
779     if (!entry)
780       continue;
781
782     if (k >= 1)
783       status = SILC_STATUS_LIST_ITEM;
784     if (valid_rcount > 1 && k == valid_rcount - 1)
785       status = SILC_STATUS_LIST_END;
786
787     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
788
789     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
790       topic = "*private*";
791       memset(usercount, 0, sizeof(usercount));
792     } else {
793       topic = entry->topic;
794       users = entry->user_count;
795       SILC_PUT32_MSB(users, usercount);
796     }
797
798     /* Send the reply */
799     packet = 
800       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
801                                            status, 0, ident, 4,
802                                            2, idp->data, idp->len,
803                                            3, entry->channel_name, 
804                                            strlen(entry->channel_name),
805                                            4, topic, topic ? strlen(topic) : 0,
806                                            5, usercount, 4);
807     silc_server_packet_send(cmd->server, cmd->sock, 
808                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
809                             packet->len, FALSE);
810     silc_buffer_free(packet);
811     silc_buffer_free(idp);
812     k++;
813   }
814 }
815
816 /* Server side of LIST command. This lists the channel of the requested
817    server. Secret channels are not listed. */
818
819 SILC_SERVER_CMD_FUNC(list)
820 {
821   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
822   SilcServer server = cmd->server;
823   SilcChannelID *channel_id = NULL;
824   unsigned char *tmp;
825   SilcUInt32 tmp_len;
826   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
827   SilcUInt32 lch_count = 0, gch_count = 0;
828
829   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
830
831   /* If we are normal server, send the command to router, since we
832      want to know all channels in the network. */
833   if (!cmd->pending && server->server_type != SILC_ROUTER && 
834       !server->standalone) {
835     SilcBuffer tmpbuf;
836     SilcUInt16 old_ident;
837     
838     old_ident = silc_command_get_ident(cmd->payload);
839     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
840     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
841     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
842                             SILC_PACKET_COMMAND, cmd->packet->flags,
843                             tmpbuf->data, tmpbuf->len, TRUE);
844
845     /* Reprocess this packet after received reply from router */
846     silc_server_command_pending(server, SILC_COMMAND_LIST, 
847                                 silc_command_get_ident(cmd->payload),
848                                 silc_server_command_list, 
849                                 silc_server_command_dup(cmd));
850     cmd->pending = TRUE;
851     silc_command_set_ident(cmd->payload, old_ident);
852     silc_buffer_free(tmpbuf);
853     goto out;
854   }
855
856   /* Get Channel ID */
857   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
858   if (tmp) {
859     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
860     if (!channel_id) {
861       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
862                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
863       goto out;
864     }
865   }
866
867   /* Get the channels from local list */
868   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
869                                        &lch_count);
870   
871   /* Get the channels from global list */
872   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
873                                        &gch_count);
874
875   /* Send the reply */
876   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
877                                       gchannels, gch_count);
878
879   silc_free(lchannels);
880   silc_free(gchannels);
881
882  out:
883   silc_server_command_free(cmd);
884 }
885
886 /* Server side of TOPIC command. Sets topic for channel and/or returns
887    current topic to client. */
888
889 SILC_SERVER_CMD_FUNC(topic)
890 {
891   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
892   SilcServer server = cmd->server;
893   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
894   SilcChannelID *channel_id;
895   SilcChannelEntry channel;
896   SilcChannelClientEntry chl;
897   SilcBuffer packet, idp;
898   unsigned char *tmp;
899   SilcUInt32 argc, tmp_len;
900   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
901
902   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
903     goto out;
904
905   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
906
907   argc = silc_argument_get_arg_num(cmd->args);
908
909   /* Get Channel ID */
910   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
911   if (!tmp) {
912     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
913                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
914     goto out;
915   }
916   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
917   if (!channel_id) {
918     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
919                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
920     goto out;
921   }
922
923   /* Check whether the channel exists */
924   channel = silc_idlist_find_channel_by_id(server->local_list, 
925                                            channel_id, NULL);
926   if (!channel) {
927     channel = silc_idlist_find_channel_by_id(server->global_list, 
928                                              channel_id, NULL);
929     if (!channel) {
930       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
931                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
932                                             0);
933       goto out;
934     }
935   }
936
937   if (argc > 1) {
938     /* Get the topic */
939     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
940     if (!tmp) {
941       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
942                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
943                                             0);
944       goto out;
945     }
946
947     if (strlen(tmp) > 256) {
948       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
949                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
950                                             0);
951       goto out;
952     }
953
954     /* See whether the client is on channel and has rights to change topic */
955     if (!silc_server_client_on_channel(client, channel, &chl)) {
956       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
957                                             SILC_STATUS_ERR_NOT_ON_CHANNEL,
958                                             0);
959       goto out;
960     }
961
962     if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
963         !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
964         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
965       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
966                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
967                                             0);
968       goto out;
969     }
970
971     if (!channel->topic || strcmp(channel->topic, tmp)) {
972       /* Set the topic for channel */
973       silc_free(channel->topic);
974       channel->topic = strdup(tmp);
975
976       /* Send TOPIC_SET notify type to the network */
977       silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
978                                         SILC_BROADCAST(server), channel,
979                                         client->id, SILC_ID_CLIENT,
980                                         channel->topic);
981
982       /* Send notify about topic change to all clients on the channel */
983       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
984       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
985                                          SILC_NOTIFY_TYPE_TOPIC_SET, 2,
986                                          idp->data, idp->len,
987                                          channel->topic,
988                                          strlen(channel->topic));
989       silc_buffer_free(idp);
990     }
991   }
992
993   /* Send the topic to client as reply packet */
994   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
995   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
996                                                 SILC_STATUS_OK, 0, ident, 2, 
997                                                 2, idp->data, idp->len,
998                                                 3, channel->topic, 
999                                                 channel->topic ? 
1000                                                 strlen(channel->topic) : 0);
1001   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1002                           0, packet->data, packet->len, FALSE);
1003
1004   silc_buffer_free(packet);
1005   silc_buffer_free(idp);
1006   silc_free(channel_id);
1007
1008  out:
1009   silc_server_command_free(cmd);
1010 }
1011
1012 /* Server side of INVITE command. Invites some client to join some channel. 
1013    This command is also used to manage the invite list of the channel. */
1014
1015 SILC_SERVER_CMD_FUNC(invite)
1016 {
1017   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1018   SilcServer server = cmd->server;
1019   SilcSocketConnection sock = cmd->sock, dest_sock;
1020   SilcChannelClientEntry chl;
1021   SilcClientEntry sender, dest;
1022   SilcClientID *dest_id = NULL;
1023   SilcChannelEntry channel;
1024   SilcChannelID *channel_id = NULL;
1025   SilcIDListData idata;
1026   SilcArgumentPayload args;
1027   SilcHashTableList htl;
1028   SilcBuffer packet, list, tmp2;
1029   unsigned char *tmp;
1030   SilcUInt32 len, type;
1031   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1032
1033   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1034
1035   /* Get Channel ID */
1036   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1037   if (!tmp) {
1038     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1039                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1040     goto out;
1041   }
1042   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1043   if (!channel_id) {
1044     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1045                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1046     goto out;
1047   }
1048
1049   /* Get the channel entry */
1050   channel = silc_idlist_find_channel_by_id(server->local_list, 
1051                                            channel_id, NULL);
1052   if (!channel) {
1053     channel = silc_idlist_find_channel_by_id(server->global_list, 
1054                                              channel_id, NULL);
1055     if (!channel) {
1056       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1057                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1058                                             0);
1059       goto out;
1060     }
1061   }
1062
1063   /* Check whether the sender of this command is on the channel. */
1064   sender = (SilcClientEntry)sock->user_data;
1065   if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1066     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1067                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
1068     goto out;
1069   }
1070
1071   /* Check whether the channel is invite-only channel. If yes then the
1072      sender of this command must be at least channel operator. */
1073   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1074       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1075       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1077                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1078                                           0);
1079     goto out;
1080   }
1081
1082   /* Get destination client ID */
1083   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1084   if (tmp) {
1085     bool resolve;
1086
1087     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1088     if (!dest_id) {
1089       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1090                                             SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1091       goto out;
1092     }
1093
1094     /* Get the client entry */
1095     dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1096     if (!dest) {
1097       if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1098         silc_server_command_send_status_reply(
1099                                         cmd, SILC_COMMAND_INVITE,
1100                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
1101         goto out;
1102       }
1103       
1104       /* The client info is being resolved. Reprocess this packet after
1105          receiving the reply to the query. */
1106       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1107                                   server->cmd_ident,
1108                                   silc_server_command_invite, 
1109                                   silc_server_command_dup(cmd));
1110       cmd->pending = TRUE;
1111       goto out;
1112     }
1113
1114     /* Check whether the requested client is already on the channel. */
1115     if (silc_server_client_on_channel(dest, channel, NULL)) {
1116       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1117                                             SILC_STATUS_ERR_USER_ON_CHANNEL,
1118                                             0);
1119       goto out;
1120     }
1121     
1122     /* Get route to the client */
1123     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, 
1124                                              &idata, NULL);
1125     if (!dest_sock) {
1126       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1127                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1128                                             0);
1129       goto out;
1130     }
1131
1132     /* Add the client to the invite list */
1133
1134     /* Allocate hash table for invite list if it doesn't exist yet */
1135     if (!channel->invite_list)
1136       channel->invite_list =
1137         silc_hash_table_alloc(0, silc_hash_ptr,
1138                               NULL, NULL, NULL,
1139                               silc_server_inviteban_destruct, channel, TRUE);
1140
1141     /* Check if the ID is in the list already */
1142     silc_hash_table_list(channel->invite_list, &htl);
1143     while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1144       if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1145         tmp = NULL;
1146         break;
1147       }
1148     }
1149     silc_hash_table_list_reset(&htl);
1150
1151     /* Add new Client ID to invite list */
1152     if (tmp) {
1153       list = silc_buffer_alloc_size(len);
1154       silc_buffer_put(list, tmp, len);
1155       silc_hash_table_add(channel->invite_list, (void *)3, list);
1156     }
1157
1158     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1159       /* Send notify to the client that is invited to the channel */
1160       SilcBuffer idp, idp2;
1161       idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1162       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1163       silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
1164                                    SILC_ID_CLIENT,
1165                                    SILC_NOTIFY_TYPE_INVITE, 3, 
1166                                    idp->data, idp->len, 
1167                                    channel->channel_name, 
1168                                    strlen(channel->channel_name),
1169                                    idp2->data, idp2->len);
1170       silc_buffer_free(idp);
1171       silc_buffer_free(idp2);
1172     }
1173   }
1174
1175   /* Get the invite information */
1176   tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
1177   if (tmp && len > 2) {
1178     /* Parse the arguments to see they are constructed correctly */
1179     SILC_GET16_MSB(argc, tmp);
1180     args = silc_argument_payload_parse(tmp + 2, len - 2, argc);
1181     if (!args) {
1182       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1183                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1184                                             0);
1185       goto out;
1186     }
1187
1188     /* Get the type of action */
1189     tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1190     if (tmp && len == 1) {
1191       if (tmp[0] == 0x00) {
1192         /* Allocate hash table for invite list if it doesn't exist yet */
1193         if (!channel->invite_list)
1194           channel->invite_list =
1195             silc_hash_table_alloc(0, silc_hash_ptr,
1196                                   NULL, NULL, NULL,
1197                                   silc_server_inviteban_destruct, channel,
1198                                   TRUE);
1199     
1200         /* Check for resource limit */
1201         if (silc_hash_table_count(channel->invite_list) > 64) {
1202           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1203                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
1204                                                 0);
1205           goto out;
1206         }
1207       }
1208
1209       /* Now add or delete the information. */
1210       silc_server_inviteban_process(server, channel->invite_list,
1211                                     (SilcUInt8)tmp[0], args);
1212     }
1213     silc_argument_payload_free(args);
1214   }
1215
1216   /* Encode invite list */
1217   list = NULL;
1218   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1219     list = silc_buffer_alloc_size(2);
1220     silc_buffer_format(list,
1221                        SILC_STR_UI_SHORT(silc_hash_table_count(
1222                                           channel->invite_list)),
1223                        SILC_STR_END);
1224     silc_hash_table_list(channel->invite_list, &htl);
1225     while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1226       if (type == 1)
1227         list = silc_argument_payload_encode_one(list, (char *)tmp2,
1228                                                 strlen((char *)tmp2), type);
1229       else
1230         list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
1231                                                 type);
1232     }
1233     silc_hash_table_list_reset(&htl);
1234   }
1235
1236   /* Send notify to the primary router */
1237   silc_server_send_notify_invite(
1238                          server, SILC_PRIMARY_ROUTE(server),
1239                          SILC_BROADCAST(server), channel, sender->id,
1240                          silc_argument_get_arg_type(cmd->args, 3, NULL),
1241                          list);
1242
1243   /* Send invite list back only if the list was modified, or now arguments
1244      was given. */
1245   type = 0;
1246   argc = silc_argument_get_arg_num(cmd->args);
1247   if (argc == 1)
1248     type = 1;
1249   if (silc_argument_get_arg_type(cmd->args, 3, &len))
1250     type = 1;
1251
1252   /* Send command reply */
1253   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1254   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1255                                                 SILC_STATUS_OK, 0, ident, 2,
1256                                                 2, tmp, len,
1257                                                 3, type && list ? 
1258                                                 list->data : NULL,
1259                                                 type && list ? list->len : 0);
1260   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1261                           packet->data, packet->len, FALSE);
1262   silc_buffer_free(packet);
1263   silc_buffer_free(list);
1264
1265  out:
1266   silc_free(dest_id);
1267   silc_free(channel_id);
1268   silc_server_command_free(cmd);
1269 }
1270
1271 typedef struct {
1272   SilcSocketConnection sock;
1273   char *signoff;
1274 } *QuitInternal;
1275
1276 /* Quits connection to client. This gets called if client won't
1277    close the connection even when it has issued QUIT command. */
1278
1279 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1280 {
1281   SilcServer server = app_context;
1282   QuitInternal q = (QuitInternal)context;
1283
1284   /* Free all client specific data, such as client entry and entires
1285      on channels this client may be on. */
1286   silc_server_free_client_data(server, q->sock, q->sock->user_data,
1287                                TRUE, q->signoff);
1288   q->sock->user_data = NULL;
1289
1290   /* Close the connection on our side */
1291   silc_server_close_connection(server, q->sock);
1292
1293   silc_socket_free(q->sock);
1294   silc_free(q->signoff);
1295   silc_free(q);
1296 }
1297
1298 /* Quits SILC session. This is the normal way to disconnect client. */
1299  
1300 SILC_SERVER_CMD_FUNC(quit)
1301 {
1302   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1303   SilcServer server = cmd->server;
1304   SilcSocketConnection sock = cmd->sock;
1305   QuitInternal q;
1306   unsigned char *tmp = NULL;
1307   SilcUInt32 len = 0;
1308
1309   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1310
1311   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1312     goto out;
1313
1314   /* Get message */
1315   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1316   if (len > 128)
1317     tmp = NULL;
1318
1319   q = silc_calloc(1, sizeof(*q));
1320   q->sock = silc_socket_dup(sock);
1321   q->signoff = tmp ? strdup(tmp) : NULL;
1322
1323   /* We quit the connection with little timeout */
1324   silc_schedule_task_add(server->schedule, sock->sock,
1325                          silc_server_command_quit_cb, (void *)q,
1326                          0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1327
1328  out:
1329   silc_server_command_free(cmd);
1330 }
1331
1332 /* Server side of command KILL. This command is used by router operator
1333    to remove an client from the SILC Network temporarily. */
1334
1335 SILC_SERVER_CMD_FUNC(kill)
1336 {
1337   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1338   SilcServer server = cmd->server;
1339   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1340   SilcClientEntry remote_client;
1341   SilcClientID *client_id = NULL;
1342   unsigned char *tmp, *comment, *auth;
1343   SilcUInt32 tmp_len, tmp_len2, auth_len;
1344
1345   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1346
1347   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1348     goto out;
1349
1350   /* Get authentication payload if present */
1351   auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1352
1353   if (!auth) {
1354     /* Router operator killing */
1355
1356     /* KILL command works only on router */
1357     if (server->server_type != SILC_ROUTER) {
1358       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1359                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1360       goto out;
1361     }
1362
1363     /* Check whether client has the permissions. */
1364     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1365       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1366                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1367       goto out;
1368     }
1369   }
1370
1371   /* Get the client ID */
1372   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1373   if (!tmp) {
1374     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1375                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1376                                           0);
1377     goto out;
1378   }
1379   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1380   if (!client_id) {
1381     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1382                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1383                                           0);
1384     goto out;
1385   }
1386
1387   /* Get the client entry */
1388   remote_client = silc_idlist_find_client_by_id(server->local_list, 
1389                                                 client_id, TRUE, NULL);
1390   if (!remote_client) {
1391     remote_client = silc_idlist_find_client_by_id(server->global_list, 
1392                                                   client_id, TRUE, NULL);
1393     if (!remote_client) {
1394       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1395                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1396                                             0);
1397       goto out;
1398     }
1399   }
1400
1401   /* Get comment */
1402   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1403   if (comment && tmp_len2 > 128) {
1404     tmp_len2 = 128;
1405     comment[127] = '\0';
1406   }
1407
1408   /* If authentication data is provided then verify that killing is
1409      actually allowed */
1410   if (auth && auth_len) {
1411     SilcSocketConnection sock;
1412
1413     if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1414       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1415                                             SILC_STATUS_ERR_OPERATION_ALLOWED,
1416                                             0);
1417       goto out;
1418     }
1419
1420     /* Verify the signature */
1421     if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1422                                remote_client->data.public_key, 0,
1423                                server->sha1hash, remote_client->id,
1424                                SILC_ID_CLIENT)) {
1425       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1426                                             SILC_STATUS_ERR_AUTH_FAILED,
1427                                             0);
1428       goto out;
1429     }
1430
1431     /* Send reply to the sender */
1432     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1433                                           SILC_STATUS_OK, 0);
1434
1435     /* Do normal signoff for the destination client */
1436     sock = remote_client->connection;
1437     silc_server_remove_from_channels(server, NULL, remote_client,
1438                                      TRUE, (char *)"Killed", TRUE, TRUE);
1439     silc_server_free_client_data(server, NULL, remote_client, TRUE,
1440                                  comment ? comment :
1441                                  (unsigned char *)"Killed");
1442     if (sock)
1443       silc_server_close_connection(server, sock);
1444   } else {
1445     /* Router operator killing */
1446
1447     /* Send reply to the sender */
1448     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1449                                           SILC_STATUS_OK, 0);
1450
1451     /* Check if anyone is watching this nickname */
1452     if (server->server_type == SILC_ROUTER)
1453       silc_server_check_watcher_list(server, client, NULL,
1454                                      SILC_NOTIFY_TYPE_KILLED);
1455
1456     /* Now do the killing */
1457     silc_server_kill_client(server, remote_client, comment, client->id,
1458                             SILC_ID_CLIENT);
1459   }
1460
1461  out:
1462   silc_free(client_id);
1463   silc_server_command_free(cmd);
1464 }
1465
1466 /* Server side of command INFO. This sends information about us to 
1467    the client. If client requested specific server we will send the 
1468    command to that server. */
1469
1470 SILC_SERVER_CMD_FUNC(info)
1471 {
1472   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1473   SilcServer server = cmd->server;
1474   SilcBuffer packet, idp;
1475   unsigned char *tmp;
1476   SilcUInt32 tmp_len;
1477   char *dest_server, *server_info = NULL, *server_name;
1478   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1479   SilcServerEntry entry = NULL;
1480   SilcServerID *server_id = NULL;
1481
1482   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1483
1484   /* Get server name */
1485   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1486
1487   /* Get Server ID */
1488   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1489   if (tmp) {
1490     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1491     if (!server_id) {
1492       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1493                                             SILC_STATUS_ERR_NO_SERVER_ID, 0);
1494       goto out;
1495     }
1496   }
1497
1498   if (server_id) {
1499     /* Check whether we have this server cached */
1500     entry = silc_idlist_find_server_by_id(server->local_list,
1501                                           server_id, TRUE, NULL);
1502     if (!entry) {
1503       entry = silc_idlist_find_server_by_id(server->global_list,
1504                                             server_id, TRUE, NULL);
1505       if (!entry && server->server_type != SILC_SERVER) {
1506         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1507                                               SILC_STATUS_ERR_NO_SUCH_SERVER,
1508                                               0);
1509         goto out;
1510       }
1511     }
1512   }
1513
1514   /* Some buggy servers has sent request to router about themselves. */
1515   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1516     goto out;
1517
1518   if ((!dest_server && !server_id && !entry) || (entry && 
1519                                                  entry == server->id_entry) ||
1520       (dest_server && !cmd->pending && 
1521        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1522     /* Send our reply */
1523     char info_string[256];
1524
1525     memset(info_string, 0, sizeof(info_string));
1526     snprintf(info_string, sizeof(info_string), 
1527              "location: %s server: %s admin: %s <%s>",
1528              server->config->server_info->location,
1529              server->config->server_info->server_type,
1530              server->config->server_info->admin,
1531              server->config->server_info->email);
1532
1533     server_info = info_string;
1534     entry = server->id_entry;
1535   } else {
1536     /* Check whether we have this server cached */
1537     if (!entry && dest_server) {
1538       entry = silc_idlist_find_server_by_name(server->global_list,
1539                                               dest_server, TRUE, NULL);
1540       if (!entry) {
1541         entry = silc_idlist_find_server_by_name(server->local_list,
1542                                                 dest_server, TRUE, NULL);
1543       }
1544     }
1545
1546     if (!cmd->pending &&
1547         server->server_type != SILC_SERVER && entry && !entry->server_info) {
1548       /* Send to the server */
1549       SilcBuffer tmpbuf;
1550       SilcUInt16 old_ident;
1551
1552       old_ident = silc_command_get_ident(cmd->payload);
1553       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1554       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1555
1556       silc_server_packet_send(server, entry->connection,
1557                               SILC_PACKET_COMMAND, cmd->packet->flags,
1558                               tmpbuf->data, tmpbuf->len, TRUE);
1559
1560       /* Reprocess this packet after received reply from router */
1561       silc_server_command_pending(server, SILC_COMMAND_INFO, 
1562                                   silc_command_get_ident(cmd->payload),
1563                                   silc_server_command_info,
1564                                   silc_server_command_dup(cmd));
1565       cmd->pending = TRUE;
1566       silc_command_set_ident(cmd->payload, old_ident);
1567       silc_buffer_free(tmpbuf);
1568       goto out;
1569     }
1570
1571     if (!entry && !cmd->pending && !server->standalone) {
1572       /* Send to the primary router */
1573       SilcBuffer tmpbuf;
1574       SilcUInt16 old_ident;
1575
1576       old_ident = silc_command_get_ident(cmd->payload);
1577       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1578       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1579
1580       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1581                               SILC_PACKET_COMMAND, cmd->packet->flags,
1582                               tmpbuf->data, tmpbuf->len, TRUE);
1583
1584       /* Reprocess this packet after received reply from router */
1585       silc_server_command_pending(server, SILC_COMMAND_INFO, 
1586                                   silc_command_get_ident(cmd->payload),
1587                                   silc_server_command_info,
1588                                   silc_server_command_dup(cmd));
1589       cmd->pending = TRUE;
1590       silc_command_set_ident(cmd->payload, old_ident);
1591       silc_buffer_free(tmpbuf);
1592       goto out;
1593     }
1594   }
1595
1596   silc_free(server_id);
1597
1598   if (!entry) {
1599     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1600                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1601     goto out;
1602   }
1603
1604   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1605   if (!server_info)
1606     server_info = entry->server_info;
1607   server_name = entry->server_name;
1608
1609   /* Send the reply */
1610   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1611                                                 SILC_STATUS_OK, 0, ident, 3,
1612                                                 2, idp->data, idp->len,
1613                                                 3, server_name, 
1614                                                 strlen(server_name),
1615                                                 4, server_info, 
1616                                                 server_info ? 
1617                                                 strlen(server_info) : 0);
1618   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1619                           packet->data, packet->len, FALSE);
1620     
1621   silc_buffer_free(packet);
1622   silc_buffer_free(idp);
1623
1624  out:
1625   silc_server_command_free(cmd);
1626 }
1627
1628 /* Server side of command PING. This just replies to the ping. */
1629
1630 SILC_SERVER_CMD_FUNC(ping)
1631 {
1632   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1633   SilcServer server = cmd->server;
1634   SilcUInt32 tmp_len;
1635   unsigned char *tmp;
1636   SilcServerID *server_id = NULL;
1637
1638   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1639
1640   /* Get Server ID */
1641   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1642   if (!tmp) {
1643     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1644                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
1645     goto out;
1646   }
1647   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1648   if (!server_id)
1649     goto out;
1650
1651   if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1652     /* Send our reply */
1653     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1654                                           SILC_STATUS_OK, 0);
1655   } else {
1656     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1657                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1658     goto out;
1659   }
1660
1661  out:
1662   silc_free(server_id);
1663   silc_server_command_free(cmd);
1664 }
1665
1666 /* Server side of command STATS. */
1667
1668 SILC_SERVER_CMD_FUNC(stats)
1669 {
1670   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1671   SilcServer server = cmd->server;
1672   SilcServerID *server_id;
1673   unsigned char *tmp;
1674   SilcUInt32 tmp_len;
1675   SilcBuffer packet, stats;
1676   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1677   SilcUInt32 uptime;
1678
1679   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1680
1681   /* Get Server ID */
1682   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1683   if (!tmp) {
1684     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1685                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
1686     goto out;
1687   }
1688   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1689   if (!server_id)
1690     goto out;
1691
1692   /* The ID must be ours */
1693   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1694     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1695                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1696     silc_free(server_id);
1697     goto out;
1698   }
1699   silc_free(server_id);
1700
1701   /* If we are router then just send everything we got. If we are normal
1702      server then we'll send this to our router to get all the latest
1703      statistical information. */
1704   if (!cmd->pending && server->server_type != SILC_ROUTER && 
1705       !server->standalone) {
1706     /* Send request to our router */
1707     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
1708                                             SILC_ID_SERVER);
1709     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
1710                                             ++server->cmd_ident, 1,
1711                                             1, idp->data, idp->len);
1712     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1713                             SILC_PACKET_COMMAND, 0, packet->data,
1714                             packet->len, FALSE);
1715
1716     /* Reprocess this packet after received reply from router */
1717     silc_server_command_pending(server, SILC_COMMAND_STATS, 
1718                                 server->cmd_ident,
1719                                 silc_server_command_stats,
1720                                 silc_server_command_dup(cmd));
1721     cmd->pending = TRUE;
1722     silc_buffer_free(packet);
1723     silc_buffer_free(idp);
1724     goto out;
1725   }
1726
1727   /* Send our reply to sender */
1728   uptime = time(NULL) - server->starttime;
1729
1730   stats = silc_buffer_alloc_size(60);
1731   silc_buffer_format(stats,
1732                      SILC_STR_UI_INT(server->starttime),
1733                      SILC_STR_UI_INT(uptime),
1734                      SILC_STR_UI_INT(server->stat.my_clients),
1735                      SILC_STR_UI_INT(server->stat.my_channels),
1736                      SILC_STR_UI_INT(server->stat.my_server_ops),
1737                      SILC_STR_UI_INT(server->stat.my_router_ops),
1738                      SILC_STR_UI_INT(server->stat.cell_clients),
1739                      SILC_STR_UI_INT(server->stat.cell_channels),
1740                      SILC_STR_UI_INT(server->stat.cell_servers),
1741                      SILC_STR_UI_INT(server->stat.clients),
1742                      SILC_STR_UI_INT(server->stat.channels),
1743                      SILC_STR_UI_INT(server->stat.servers),
1744                      SILC_STR_UI_INT(server->stat.routers),
1745                      SILC_STR_UI_INT(server->stat.server_ops),
1746                      SILC_STR_UI_INT(server->stat.router_ops),
1747                      SILC_STR_END);
1748
1749   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
1750                                                 SILC_STATUS_OK, 0, ident, 2,
1751                                                 2, tmp, tmp_len,
1752                                                 3, stats->data, stats->len);
1753   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1754                           0, packet->data, packet->len, FALSE);
1755   silc_buffer_free(packet);
1756   silc_buffer_free(stats);
1757
1758  out:
1759   silc_server_command_free(cmd);
1760 }
1761
1762 /* Internal routine to join channel. The channel sent to this function
1763    has been either created or resolved from ID lists. This joins the sent
1764    client to the channel. */
1765
1766 static void silc_server_command_join_channel(SilcServer server, 
1767                                              SilcServerCommandContext cmd,
1768                                              SilcChannelEntry channel,
1769                                              SilcClientID *client_id,
1770                                              bool created,
1771                                              bool create_key,
1772                                              SilcUInt32 umode,
1773                                              const unsigned char *auth,
1774                                              SilcUInt32 auth_len)
1775 {
1776   SilcSocketConnection sock = cmd->sock;
1777   unsigned char *tmp;
1778   SilcUInt32 tmp_len, user_count;
1779   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1780   SilcClientEntry client;
1781   SilcChannelClientEntry chl;
1782   SilcBuffer reply, chidp, clidp, keyp = NULL;
1783   SilcBuffer user_list, mode_list, invite_list, ban_list;
1784   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1785   char check[512], check2[512];
1786   bool founder = FALSE;
1787   bool resolve;
1788   SilcBuffer fkey = NULL;
1789   const char *cipher;
1790
1791   SILC_LOG_DEBUG(("Joining client to channel"));
1792
1793   if (!channel)
1794     return;
1795
1796   /* Get the client entry */
1797   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1798     client = (SilcClientEntry)sock->user_data;
1799     if (!client)
1800       return;
1801   } else {
1802     client = silc_server_query_client(server, client_id, FALSE, 
1803                                       &resolve);
1804     if (!client) {
1805       if (!resolve || cmd->pending) {
1806         silc_server_command_send_status_reply(
1807                                          cmd, SILC_COMMAND_JOIN,
1808                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1809         goto out;
1810       }
1811
1812       /* The client info is being resolved. Reprocess this packet after
1813          receiving the reply to the query. */
1814       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1815                                   server->cmd_ident,
1816                                   silc_server_command_join, 
1817                                   silc_server_command_dup(cmd));
1818       cmd->pending = TRUE;
1819       goto out;
1820     }
1821
1822     if (auth && auth_len && !client->data.public_key) {
1823       if (cmd->pending == 2)
1824         goto out;
1825
1826       /* We must retrieve the detached client's public key by sending
1827          GETKEY command. Reprocess this packet after receiving the key */
1828       clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1829       silc_server_send_command(server, cmd->sock,
1830                                SILC_COMMAND_GETKEY, ++server->cmd_ident,
1831                                1, 1, clidp->data, clidp->len);
1832       silc_buffer_free(clidp);
1833       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1834                                   server->cmd_ident,
1835                                   silc_server_command_join, 
1836                                   silc_server_command_dup(cmd));
1837       cmd->pending = 2;
1838       goto out;
1839     }
1840
1841     cmd->pending = FALSE;
1842   }
1843
1844   /*
1845    * Check founder auth payload if provided.  If client can gain founder
1846    * privileges it can override various conditions on joining the channel,
1847    * and can have directly the founder mode set on the channel.
1848    */
1849   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1850     SilcIDListData idata = (SilcIDListData)client;
1851     SilcChannelClientEntry chl2;
1852     SilcHashTableList htl;
1853
1854     if (channel->founder_key && idata->public_key &&
1855         silc_pkcs_public_key_compare(channel->founder_key, 
1856                                      idata->public_key)) {
1857       /* Check whether the client is to become founder */
1858       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1859                                 channel->founder_key, 0, server->sha1hash,
1860                                 client->id, SILC_ID_CLIENT)) {
1861
1862         /* There cannot be anyone else as founder on the channel now.  This
1863            client is definitely the founder due to this authentication */
1864         silc_hash_table_list(channel->user_list, &htl);
1865         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1866           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1867             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1868             silc_server_force_cumode_change(server, NULL, channel, chl2,
1869                                             chl2->mode);
1870             break;
1871           }
1872         silc_hash_table_list_reset(&htl);
1873
1874         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1875         founder = TRUE;
1876       }
1877     }
1878   }
1879
1880   /*
1881    * Check channel modes
1882    */
1883
1884   if (!umode) {
1885     memset(check, 0, sizeof(check));
1886     memset(check2, 0, sizeof(check2));
1887     silc_strncat(check, sizeof(check),
1888                  client->nickname, strlen(client->nickname));
1889     silc_strncat(check, sizeof(check), "!", 1);
1890     silc_strncat(check, sizeof(check),
1891                  client->username, strlen(client->username));
1892     if (!strchr(client->username, '@')) {
1893       silc_strncat(check, sizeof(check), "@", 1);
1894       silc_strncat(check, sizeof(check),
1895                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1896     }
1897
1898     silc_strncat(check2, sizeof(check2),
1899                  client->nickname, strlen(client->nickname));
1900     if (!strchr(client->nickname, '@')) {
1901       silc_strncat(check2, sizeof(check2), "@", 1);
1902       silc_strncat(check2, sizeof(check2),
1903                    server->server_name, strlen(server->server_name));
1904     }
1905     silc_strncat(check2, sizeof(check2), "!", 1);
1906     silc_strncat(check2, sizeof(check2),
1907                  client->username, strlen(client->username));
1908     if (!strchr(client->username, '@')) {
1909       silc_strncat(check2, sizeof(check2), "@", 1);
1910       silc_strncat(check2, sizeof(check2),
1911                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1912     }
1913     
1914     /* Check invite list if channel is invite-only channel */
1915     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1916       if (!channel->invite_list ||
1917           !silc_hash_table_count(channel->invite_list) ||
1918           (!silc_server_inviteban_match(server, channel->invite_list,
1919                                         3, client->id) &&
1920            !silc_server_inviteban_match(server, channel->invite_list,
1921                                         2, client->data.public_key) &&
1922            !silc_server_inviteban_match(server, channel->invite_list,
1923                                         1, check) &&
1924            !silc_server_inviteban_match(server, channel->invite_list,
1925                                         1, check2))) {
1926         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1927                                               SILC_STATUS_ERR_NOT_INVITED, 0);
1928         goto out;
1929       }
1930     }
1931
1932     /* Check ban list if it exists. If the client's nickname, server,
1933        username and/or hostname is in the ban list the access to the
1934        channel is denied. */
1935     if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
1936       if (silc_server_inviteban_match(server, channel->ban_list,
1937                                       3, client->id) ||
1938           silc_server_inviteban_match(server, channel->ban_list,
1939                                       2, client->data.public_key) ||
1940           silc_server_inviteban_match(server, channel->ban_list,
1941                                       1, check) ||
1942           silc_server_inviteban_match(server, channel->ban_list,
1943                                       1, check2)) {
1944         silc_server_command_send_status_reply(
1945                                       cmd, SILC_COMMAND_JOIN,
1946                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1947         goto out;
1948       }
1949     }
1950     
1951     /* Check user count limit if set. */
1952     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1953       if (silc_hash_table_count(channel->user_list) + 1 > 
1954           channel->user_limit) {
1955         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1956                                               SILC_STATUS_ERR_CHANNEL_IS_FULL,
1957                                               0);
1958         goto out;
1959       }
1960     }
1961   }
1962
1963   /* Check the channel passphrase if set. */
1964   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1965     /* Get passphrase */
1966     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1967     if (tmp)
1968       passphrase = silc_memdup(tmp, tmp_len);
1969   
1970     if (!passphrase || !channel->passphrase ||
1971         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1972       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1973                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
1974       goto out;
1975     }
1976   }
1977
1978   /*
1979    * Client is allowed to join to the channel. Make it happen.
1980    */
1981
1982   /* Check whether the client already is on the channel */
1983   if (silc_server_client_on_channel(client, channel, NULL)) {
1984     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1985                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1986     goto out;
1987   }
1988
1989   /* Generate new channel key as protocol dictates */
1990   if (create_key) {
1991     if (!silc_server_create_channel_key(server, channel, 0))
1992       goto out;
1993
1994     /* Send the channel key. This is broadcasted to the channel but is not
1995        sent to the client who is joining to the channel. */
1996     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1997       silc_server_send_channel_key(server, NULL, channel, 
1998                                    server->server_type == SILC_ROUTER ? 
1999                                    FALSE : !server->standalone);
2000   }
2001
2002   /* Join the client to the channel by adding it to channel's user list.
2003      Add also the channel to client entry's channels list for fast cross-
2004      referencing. */
2005   chl = silc_calloc(1, sizeof(*chl));
2006   chl->mode = umode;
2007   chl->client = client;
2008   chl->channel = channel;
2009   silc_hash_table_add(channel->user_list, client, chl);
2010   silc_hash_table_add(client->channels, channel, chl);
2011   channel->user_count++;
2012   channel->disabled = FALSE;
2013
2014   /* Get users on the channel */
2015   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2016                                    &user_count);
2017
2018   /* Encode Client ID Payload of the original client who wants to join */
2019   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2020
2021   /* Encode command reply packet */
2022   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2023   SILC_PUT32_MSB(channel->mode, mode);
2024   SILC_PUT32_MSB(created, tmp2);
2025   SILC_PUT32_MSB(user_count, tmp3);
2026
2027   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2028     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2029     cipher = silc_cipher_get_name(channel->channel_key);
2030     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2031                                                            SILC_ID_CHANNEL), 
2032                                            tmp,
2033                                            strlen(cipher), cipher,
2034                                            channel->key_len / 8, channel->key);
2035     silc_free(tmp);
2036   }
2037
2038   if (channel->founder_key)
2039     fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2040
2041   /* Encode invite list */
2042   invite_list = NULL;
2043   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2044     SilcHashTableList htl;
2045
2046     invite_list = silc_buffer_alloc_size(2);
2047     silc_buffer_format(invite_list,
2048                        SILC_STR_UI_SHORT(silc_hash_table_count(
2049                                           channel->invite_list)),
2050                        SILC_STR_END);
2051
2052     silc_hash_table_list(channel->invite_list, &htl);
2053     while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
2054       if (tmp_len == 1)
2055         invite_list = silc_argument_payload_encode_one(invite_list,
2056                                                        (char *)reply,
2057                                                        strlen((char *)reply),
2058                                                        tmp_len);
2059       else
2060         invite_list = silc_argument_payload_encode_one(invite_list,
2061                                                        reply->data,
2062                                                        reply->len, tmp_len);
2063     }
2064     silc_hash_table_list_reset(&htl);
2065   }
2066
2067   /* Encode ban list */
2068   ban_list = NULL;
2069   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2070     SilcHashTableList htl;
2071
2072     ban_list = silc_buffer_alloc_size(2);
2073     silc_buffer_format(ban_list,
2074                        SILC_STR_UI_SHORT(silc_hash_table_count(
2075                                           channel->ban_list)),
2076                        SILC_STR_END);
2077
2078     silc_hash_table_list(channel->ban_list, &htl);
2079     while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
2080       if (tmp_len == 1)
2081         ban_list = silc_argument_payload_encode_one(ban_list,
2082                                                     (char *)reply,
2083                                                     strlen((char *)reply),
2084                                                     tmp_len);
2085       else
2086         ban_list = silc_argument_payload_encode_one(ban_list,
2087                                                     reply->data,
2088                                                     reply->len, tmp_len);
2089     }
2090     silc_hash_table_list_reset(&htl);
2091   }
2092
2093   reply = 
2094     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2095                                          SILC_STATUS_OK, 0, ident, 14,
2096                                          2, channel->channel_name,
2097                                          strlen(channel->channel_name),
2098                                          3, chidp->data, chidp->len,
2099                                          4, clidp->data, clidp->len,
2100                                          5, mode, 4,
2101                                          6, tmp2, 4,
2102                                          7, keyp ? keyp->data : NULL, 
2103                                          keyp ? keyp->len : 0,
2104                                          8, ban_list ? ban_list->data : NULL,
2105                                          ban_list ? ban_list->len : 0,
2106                                          9, invite_list ? invite_list->data :
2107                                          NULL,
2108                                          invite_list ? invite_list->len : 0,
2109                                          10, channel->topic,
2110                                          channel->topic ?
2111                                          strlen(channel->topic) : 0,
2112                                          11, silc_hmac_get_name(channel->hmac),
2113                                          strlen(silc_hmac_get_name(channel->
2114                                                                    hmac)),
2115                                          12, tmp3, 4,
2116                                          13, user_list->data, user_list->len,
2117                                          14, mode_list->data, 
2118                                          mode_list->len,
2119                                          15, fkey ? fkey->data : NULL,
2120                                          fkey ? fkey->len : 0);
2121
2122   /* Send command reply */
2123   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2124                           reply->data, reply->len, FALSE);
2125
2126   /* Send JOIN notify to locally connected clients on the channel. If
2127      we are normal server then router will send or have sent JOIN notify
2128      already. However since we've added the client already to our channel
2129      we'll ignore it (in packet_receive.c) so we must send it here. If
2130      we are router then this will send it to local clients and local
2131      servers. */
2132   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2133   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2134                                      SILC_NOTIFY_TYPE_JOIN, 2,
2135                                      clidp->data, clidp->len,
2136                                      chidp->data, chidp->len);
2137
2138   /* Update statistics */
2139   server->stat.my_chanclients++;
2140   if (server->server_type == SILC_ROUTER) {
2141     server->stat.cell_chanclients++;
2142     server->stat.chanclients++;
2143   }
2144
2145   if (!cmd->pending) {
2146     /* Send JOIN notify packet to our primary router */
2147     silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2148                                  SILC_BROADCAST(server), channel, client->id);
2149
2150     if (keyp)
2151       /* Distribute the channel key to all backup routers. */
2152       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2153                               keyp->data, keyp->len, FALSE, TRUE);
2154
2155     /* If client became founder by providing correct founder auth data
2156        notify the mode change to the channel. */
2157     if (founder) {
2158       SILC_PUT32_MSB(chl->mode, mode);
2159       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2160       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2161                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2162                                          clidp->data, clidp->len,
2163                                          mode, 4, clidp->data, clidp->len,
2164                                          fkey ? fkey->data : NULL,
2165                                          fkey ? fkey->len : 0);
2166     }
2167   }
2168
2169   /* Set CUMODE notify type to network */
2170   if (founder)
2171     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2172                                    SILC_BROADCAST(server), channel,
2173                                    chl->mode, client->id, SILC_ID_CLIENT,
2174                                    client->id, channel->founder_key);
2175
2176   silc_buffer_free(reply);
2177   silc_buffer_free(clidp);
2178   silc_buffer_free(chidp);
2179   silc_buffer_free(keyp);
2180   silc_buffer_free(user_list);
2181   silc_buffer_free(mode_list);
2182   silc_buffer_free(fkey);
2183   silc_buffer_free(invite_list);
2184   silc_buffer_free(ban_list);
2185
2186  out:
2187   if (passphrase)
2188     memset(passphrase, 0, strlen(passphrase));
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 }