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