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