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