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