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