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