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