Added preliminary support for dynamic connection during joining.
[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 void silc_server_command_join_connected(SilcServer server,
2298                                         SilcServerEntry server_entry,
2299                                         void *context)
2300 {
2301   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2302
2303   if (!server_entry) {
2304     SilcUInt32 tmp_len;
2305     unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2306     char serv[256 + 1];
2307
2308     SILC_LOG_DEBUG(("Connecting to router failed"));
2309     silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
2310
2311     if (serv[0]) {
2312       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2313                                            SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2314                                            2, serv, strlen(serv));
2315     } else {
2316       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2317                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
2318                                            2, tmp, tmp_len);
2319     }
2320     silc_server_command_free(cmd);
2321     return;
2322   }
2323
2324   /* Reprocess command */
2325   SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
2326   silc_server_command_join(cmd, NULL);
2327 }
2328
2329 SILC_SERVER_CMD_FUNC(join)
2330 {
2331   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2332   SilcServer server = cmd->server;
2333   SilcIDListData idata = silc_packet_get_context(cmd->sock);
2334   unsigned char *auth, *cauth;
2335   SilcUInt32 tmp_len, auth_len, cauth_len;
2336   char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
2337   char parsed[256 + 1], serv[256 + 1];
2338   SilcChannelEntry channel;
2339   SilcUInt32 umode = 0;
2340   SilcBool created = FALSE, create_key = TRUE;
2341   SilcID id;
2342
2343   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2344
2345   /* Get channel name */
2346   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2347   if (!tmp) {
2348     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2349                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2350                                           0);
2351     goto out;
2352   }
2353
2354   /* Truncate over long channel names */
2355   if (tmp_len > 256) {
2356     tmp_len = 256;
2357     tmp[tmp_len - 1] = '\0';
2358   }
2359
2360   /* Parse server name from the channel name */
2361   silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
2362                       sizeof(serv));
2363   channel_name = parsed;
2364
2365   /* If server name is not specified but local channels is FALSE then the
2366      channel will be global, based on our router name. */
2367   if (!serv[0] && !server->config->local_channels) {
2368     if (!server->standalone) {
2369       silc_snprintf(serv, sizeof(serv), server->router->server_name);
2370     } else {
2371       SilcServerConfigRouter *router;
2372       router = silc_server_config_get_primary_router(server);
2373       if (router) {
2374         /* Create connection to primary router */
2375         SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2376                         router->host, router->port));
2377         silc_server_create_connection(server, FALSE, TRUE,
2378                                       router->host, router->port,
2379                                       silc_server_command_join_connected, cmd);
2380         return;
2381       }
2382     }
2383   }
2384
2385   /* If server name is ours, ignore it. */
2386   if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
2387     memset(serv, 0, sizeof(serv));
2388
2389   /* Create connection */
2390   if (serv[0] && server->standalone) {
2391     SilcServerConfigRouter *router;
2392     router = silc_server_config_get_primary_router(server);
2393     if (router) {
2394       /* Create connection to primary router */
2395       SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2396                       router->host, router->port));
2397       silc_server_create_connection(server, FALSE, TRUE,
2398                                     router->host, router->port,
2399                                     silc_server_command_join_connected, cmd);
2400       return;
2401     }
2402   }
2403
2404   /* Check for valid channel name.  This is cached, the original is saved
2405      in the channel context. */
2406   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
2407                                           SILC_STRING_UTF8, 256, NULL);
2408   if (!channel_namec) {
2409     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2410                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
2411     goto out;
2412   }
2413
2414   /* Get Client ID of the client who is joining to the channel */
2415   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
2416     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2417                                           SILC_STATUS_ERR_NO_CLIENT_ID,
2418                                           0);
2419     goto out;
2420   }
2421   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2422
2423   /* Get cipher, hmac name and auth payload */
2424   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2425   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2426   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2427   cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2428
2429   /* See if the channel exists */
2430   channel = silc_idlist_find_channel_by_name(server->local_list,
2431                                              channel_namec, NULL);
2432
2433   if (idata->conn_type == SILC_CONN_CLIENT) {
2434     SilcClientEntry entry = (SilcClientEntry)idata;
2435     if (!entry) {
2436       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2437                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2438                                             0);
2439       goto out;
2440     }
2441
2442 #ifndef SILC_DIST_INPLACE
2443     /* Limit how many channels client can join */
2444     if (!cmd->pending && entry->channels &&
2445         silc_hash_table_count(entry->channels) >=
2446         server->config->param.chlimit) {
2447       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2448                                             SILC_STATUS_ERR_RESOURCE_LIMIT,
2449                                             0);
2450       goto out;
2451     }
2452 #endif /* SILC_DIST_INPLACE */
2453
2454     if (!channel ||
2455         (channel->disabled && server->server_type != SILC_ROUTER)) {
2456       /* Channel not found or not valid */
2457
2458       /* If we are standalone server we don't have a router, we just create
2459          the channel by ourselves (unless it existed). */
2460       if (server->standalone) {
2461         if (!channel) {
2462           channel = silc_server_create_new_channel(server, server->id, cipher,
2463                                                    hmac, channel_name, TRUE);
2464           if (!channel) {
2465             silc_server_command_send_status_data(
2466                                   cmd, SILC_COMMAND_JOIN,
2467                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2468                                   0, 2, cipher, strlen(cipher));
2469             goto out;
2470           }
2471
2472           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2473           created = TRUE;
2474           create_key = FALSE;
2475         }
2476       } else {
2477
2478         /* The channel does not exist on our server. If we are normal server
2479            we will send JOIN command to our router which will handle the
2480            joining procedure (either creates the channel if it doesn't exist
2481            or joins the client to it). */
2482         if (server->server_type != SILC_ROUTER) {
2483           SilcBuffer tmpbuf;
2484           SilcUInt16 old_ident;
2485
2486           /* If this is pending command callback then we've resolved
2487              it and it didn't work, return since we've notified the
2488              client already in the command reply callback. */
2489           if (cmd->pending)
2490             goto out;
2491
2492           /* Statistics */
2493           cmd->server->stat.commands_sent++;
2494
2495           old_ident = silc_command_get_ident(cmd->payload);
2496           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2497           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2498
2499           /* Send JOIN command to our router */
2500           silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2501                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2502                                   tmpbuf->data, silc_buffer_len(tmpbuf));
2503
2504           /* Reprocess this packet after received reply from router */
2505           silc_server_command_pending(server, SILC_COMMAND_JOIN,
2506                                       silc_command_get_ident(cmd->payload),
2507                                       silc_server_command_join,
2508                                       silc_server_command_dup(cmd));
2509           cmd->pending = TRUE;
2510           silc_command_set_ident(cmd->payload, old_ident);
2511           silc_buffer_free(tmpbuf);
2512           goto out;
2513         }
2514
2515         /* We are router and the channel does not seem exist so we will check
2516            our global list as well for the channel. */
2517         channel = silc_idlist_find_channel_by_name(server->global_list,
2518                                                    channel_namec, NULL);
2519         if (!channel) {
2520           /* Channel really does not exist, create it */
2521           channel = silc_server_create_new_channel(server, server->id, cipher,
2522                                                    hmac, channel_name, TRUE);
2523           if (!channel) {
2524             silc_server_command_send_status_data(
2525                                        cmd, SILC_COMMAND_JOIN,
2526                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2527                                        2, cipher, strlen(cipher));
2528             goto out;
2529           }
2530
2531           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2532           created = TRUE;
2533           create_key = FALSE;
2534         }
2535       }
2536     }
2537   } else {
2538     if (!channel) {
2539       /* Channel not found */
2540
2541       /* If the command came from router and we are normal server then
2542          something went wrong with the joining as the channel was not found.
2543          We can't do anything else but ignore this. */
2544       if (idata->conn_type == SILC_CONN_ROUTER ||
2545           server->server_type != SILC_ROUTER)
2546         goto out;
2547
2548       /* We are router and the channel does not seem exist so we will check
2549          our global list as well for the channel. */
2550       channel = silc_idlist_find_channel_by_name(server->global_list,
2551                                                  channel_namec, NULL);
2552       if (!channel) {
2553         /* Channel really does not exist, create it */
2554         channel = silc_server_create_new_channel(server, server->id, cipher,
2555                                                  hmac, channel_name, TRUE);
2556         if (!channel) {
2557           silc_server_command_send_status_data(
2558                                        cmd, SILC_COMMAND_JOIN,
2559                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2560                                        2, cipher, strlen(cipher));
2561           goto out;
2562         }
2563
2564         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2565         created = TRUE;
2566         create_key = FALSE;
2567       }
2568     }
2569   }
2570
2571   /* Check whether the channel was created by our router */
2572   if (cmd->pending && context2) {
2573     SilcServerCommandReplyContext reply = context2;
2574
2575     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2576       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2577       SILC_GET32_MSB(created, tmp);
2578       if (silc_argument_get_arg_type(reply->args, 7, NULL))
2579         create_key = FALSE;     /* Router returned the key already */
2580
2581       if (silc_command_get_status(reply->payload, NULL, NULL) &&
2582           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2583         /* Save channel passphrase, if user provided it successfully */
2584         unsigned char *pa;
2585         SilcUInt32 pa_len;
2586         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2587         if (pa) {
2588           silc_free(channel->passphrase);
2589           channel->passphrase = silc_memdup(pa, pa_len);
2590         }
2591       }
2592     }
2593
2594     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2595         !channel->disabled && !silc_hash_table_count(channel->user_list))
2596       created = TRUE;
2597   }
2598
2599   /* If the channel does not have global users and is also empty the client
2600      will be the channel founder and operator. */
2601   if (!channel->disabled &&
2602       !channel->global_users && !silc_hash_table_count(channel->user_list))
2603     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2604
2605   /* Join to the channel */
2606   silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
2607                                    created, create_key, umode,
2608                                    auth, auth_len, cauth, cauth_len);
2609
2610  out:
2611   silc_free(channel_namec);
2612   silc_server_command_free(cmd);
2613 }
2614
2615 /* Server side of command MOTD. Sends server's current "message of the
2616    day" to the client. */
2617
2618 SILC_SERVER_CMD_FUNC(motd)
2619 {
2620   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2621   SilcServer server = cmd->server;
2622   SilcBuffer idp;
2623   char *motd, *dest_server = NULL;
2624   SilcUInt32 motd_len;
2625   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2626
2627   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2628
2629   /* Get server name */
2630   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2631   if (!dest_server) {
2632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2633                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2634                                           0);
2635     goto out;
2636   }
2637
2638   /* Check server name */
2639   dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2640                                       SILC_STRING_UTF8, 256, NULL);
2641   if (!dest_server) {
2642     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2643                                           SILC_STATUS_ERR_BAD_SERVER,
2644                                           0);
2645     goto out;
2646   }
2647
2648   if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2649     /* Send our MOTD */
2650
2651     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2652
2653     if (server->config && server->config->server_info &&
2654         server->config->server_info->motd_file) {
2655       /* Send motd */
2656       motd = silc_file_readfile(server->config->server_info->motd_file,
2657                                 &motd_len);
2658       if (!motd) {
2659         /* No motd */
2660         silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2661                                        SILC_STATUS_OK, 0, ident, 1,
2662                                        2, idp->data, silc_buffer_len(idp));
2663         goto out;
2664       }
2665
2666       motd[motd_len] = 0;
2667       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2668                                      SILC_STATUS_OK, 0, ident, 2,
2669                                      2, idp->data, silc_buffer_len(idp),
2670                                      3, motd, motd_len);
2671     } else {
2672       /* No motd */
2673       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2674                                      SILC_STATUS_OK, 0, ident, 1,
2675                                      2, idp->data, silc_buffer_len(idp));
2676     }
2677     silc_buffer_free(idp);
2678   } else {
2679     SilcServerEntry entry;
2680
2681     /* Check whether we have this server cached */
2682     entry = silc_idlist_find_server_by_name(server->global_list,
2683                                             dest_server, TRUE, NULL);
2684     if (!entry) {
2685       entry = silc_idlist_find_server_by_name(server->local_list,
2686                                               dest_server, TRUE, NULL);
2687     }
2688
2689     if (server->server_type != SILC_SERVER && !cmd->pending &&
2690         entry && !entry->motd) {
2691       /* Send to the server */
2692       SilcBuffer tmpbuf;
2693       SilcUInt16 old_ident;
2694
2695       /* Statistics */
2696       cmd->server->stat.commands_sent++;
2697
2698       old_ident = silc_command_get_ident(cmd->payload);
2699       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2700       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2701
2702       silc_server_packet_send(server, entry->connection,
2703                               SILC_PACKET_COMMAND, cmd->packet->flags,
2704                               tmpbuf->data, silc_buffer_len(tmpbuf));
2705
2706       /* Reprocess this packet after received reply from router */
2707       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2708                                   silc_command_get_ident(cmd->payload),
2709                                   silc_server_command_motd,
2710                                   silc_server_command_dup(cmd));
2711       cmd->pending = TRUE;
2712       silc_command_set_ident(cmd->payload, old_ident);
2713       silc_buffer_free(tmpbuf);
2714       goto out;
2715     }
2716
2717     /* Send to primary router only if we don't know the server
2718      * the client requested or if the server is not locally connected */
2719     if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2720         && !cmd->pending && !server->standalone) {
2721       /* Send to the primary router */
2722       SilcBuffer tmpbuf;
2723       SilcUInt16 old_ident;
2724
2725       /* Statistics */
2726       cmd->server->stat.commands_sent++;
2727
2728       old_ident = silc_command_get_ident(cmd->payload);
2729       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2730       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2731
2732       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2733                               SILC_PACKET_COMMAND, cmd->packet->flags,
2734                               tmpbuf->data, silc_buffer_len(tmpbuf));
2735
2736       /* Reprocess this packet after received reply from router */
2737       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2738                                   silc_command_get_ident(cmd->payload),
2739                                   silc_server_command_motd,
2740                                   silc_server_command_dup(cmd));
2741       cmd->pending = TRUE;
2742       silc_command_set_ident(cmd->payload, old_ident);
2743       silc_buffer_free(tmpbuf);
2744       goto out;
2745     }
2746
2747     if (!entry) {
2748       silc_free(dest_server);
2749       dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2750       silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2751                                            SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2752                                            2, dest_server,
2753                                            strlen(dest_server));
2754       dest_server = NULL;
2755       goto out;
2756     }
2757
2758     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2759     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2760                                    SILC_STATUS_OK, 0, ident, 2,
2761                                    2, idp->data, silc_buffer_len(idp),
2762                                    3, entry->motd,
2763                                    entry->motd ?
2764                                    strlen(entry->motd) : 0);
2765     silc_buffer_free(idp);
2766   }
2767
2768  out:
2769   silc_free(dest_server);
2770   silc_server_command_free(cmd);
2771 }
2772
2773 /* Server side of command UMODE. Client can use this command to set/unset
2774    user mode. Client actually cannot set itself to be as server/router
2775    operator so this can be used only to unset the modes. */
2776
2777 SILC_SERVER_CMD_FUNC(umode)
2778 {
2779   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2780   SilcServer server = cmd->server;
2781   SilcClientEntry client = silc_packet_get_context(cmd->sock);
2782   unsigned char *tmp_mask, m[4];
2783   SilcUInt32 mask = 0;
2784   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2785   SilcBool set_mask = FALSE;
2786
2787   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
2788     goto out;
2789
2790   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2791
2792   /* Get the client's mode mask */
2793   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2794   if (tmp_mask) {
2795     SILC_GET32_MSB(mask, tmp_mask);
2796     set_mask = TRUE;
2797   }
2798
2799   if (set_mask) {
2800     /* Check that mode changing is allowed. */
2801     if (!silc_server_check_umode_rights(server, client, mask)) {
2802       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2803                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2804       goto out;
2805     }
2806
2807     /* Anonymous mode cannot be set by client */
2808     if (mask & SILC_UMODE_ANONYMOUS &&
2809         !(client->mode & SILC_UMODE_ANONYMOUS)) {
2810       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2811                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2812       goto out;
2813     }
2814
2815     /* Update statistics */
2816     if (mask & SILC_UMODE_GONE) {
2817       if (!(client->mode & SILC_UMODE_GONE))
2818         server->stat.my_aways++;
2819     } else {
2820       if (client->mode & SILC_UMODE_GONE)
2821         server->stat.my_aways--;
2822     }
2823
2824     /* If the client has anonymous mode set, preserve it. */
2825     if (client->mode & SILC_UMODE_ANONYMOUS)
2826       mask |= SILC_UMODE_ANONYMOUS;
2827
2828     /* Change the mode */
2829     client->mode = mask;
2830
2831     /* Send UMODE change to primary router */
2832     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2833                                   SILC_BROADCAST(server), client->id,
2834                                   client->mode);
2835
2836     /* Check if anyone is watching this nickname */
2837     if (server->server_type == SILC_ROUTER)
2838       silc_server_check_watcher_list(server, client, NULL,
2839                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
2840   }
2841
2842   /* Send command reply to sender */
2843   SILC_PUT32_MSB(client->mode, m);
2844   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2845                                  SILC_STATUS_OK, 0, ident, 1,
2846                                  2, m, sizeof(m));
2847
2848  out:
2849   silc_server_command_free(cmd);
2850 }
2851
2852 /* Server side command of CMODE. Changes channel mode */
2853
2854 SILC_SERVER_CMD_FUNC(cmode)
2855 {
2856   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2857   SilcServer server = cmd->server;
2858   SilcClientEntry client = silc_packet_get_context(cmd->sock);
2859   SilcIDListData idata = (SilcIDListData)client;
2860   SilcID id;
2861   SilcChannelEntry channel;
2862   SilcChannelClientEntry chl;
2863   SilcBuffer cidp;
2864   unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2865   char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2866   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2867   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2868   SilcBool set_mask = FALSE, set_chpk = FALSE;
2869   SilcPublicKey founder_key = NULL;
2870   SilcBuffer fkey = NULL, chpklist = NULL;
2871   SilcBufferStruct chpk;
2872
2873   if (!client) {
2874     silc_server_command_free(cmd);
2875     return;
2876   }
2877
2878   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2879
2880   /* Get Channel ID */
2881   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
2882     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2883                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2884     silc_server_command_free(cmd);
2885     return;
2886   }
2887
2888   /* Get channel entry */
2889   channel = silc_idlist_find_channel_by_id(server->local_list,
2890                                            SILC_ID_GET_ID(id), NULL);
2891   if (!channel) {
2892     channel = silc_idlist_find_channel_by_id(server->global_list,
2893                                              SILC_ID_GET_ID(id), NULL);
2894     if (!channel) {
2895       tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2896       silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2897                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2898                                            0, 2, tmp_id, tmp_len2);
2899       silc_server_command_free(cmd);
2900       return;
2901     }
2902   }
2903   old_mask = channel->mode;
2904
2905   /* Get the channel mode mask */
2906   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2907   if (tmp_mask) {
2908     SILC_GET32_MSB(mode_mask, tmp_mask);
2909     set_mask = TRUE;
2910   }
2911
2912   /* Check whether this client is on the channel */
2913   if (!silc_server_client_on_channel(client, channel, &chl)) {
2914     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2915     silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2916                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2917                                          2, tmp_id, tmp_len2);
2918     goto out;
2919   }
2920
2921   /* Check that client has rights to change any requested channel modes */
2922   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2923                                                   mode_mask)) {
2924     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2925     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2926     silc_server_command_send_status_data(
2927                              cmd, SILC_COMMAND_CMODE,
2928                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2929                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2930                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2931                              2, tmp_id, tmp_len2);
2932     goto out;
2933   }
2934
2935   /* If mode mask was not sent as argument then merely return the current
2936      mode mask, founder key and channel public key list to the sender. */
2937   if (!set_mask) {
2938     unsigned char m[4];
2939     SILC_PUT32_MSB(channel->mode, m);
2940     if (channel->founder_key)
2941       fkey = silc_public_key_payload_encode(channel->founder_key);
2942     if (channel->channel_pubkeys)
2943       chpklist = silc_server_get_channel_pk_list(server, channel,
2944                                                  FALSE, FALSE);
2945     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2946     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
2947                                    SILC_STATUS_OK, 0, ident, 4,
2948                                    2, tmp_id, tmp_len2,
2949                                    3, m, sizeof(m),
2950                                    4, fkey ? fkey->data : NULL,
2951                                    fkey ? silc_buffer_len(fkey) : 0,
2952                                    5, chpklist ? chpklist->data : NULL,
2953                                    chpklist ? silc_buffer_len(chpklist) : 0);
2954     goto out;
2955   }
2956
2957   /*
2958    * Check the modes. Modes that requires nothing special operation are
2959    * not checked here.
2960    */
2961
2962   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2963     /* Channel uses private keys to protect traffic. Client(s) has set the
2964        key locally they want to use, server does not know that key. */
2965     /* Nothing interesting to do here */
2966   } else {
2967     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2968       /* The mode is removed and we need to generate and distribute
2969          new channel key. Clients are not using private channel keys
2970          anymore after this. */
2971
2972       /* if we don't remove the flag from the mode
2973        * silc_server_create_channel_key won't create a new key */
2974       channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
2975
2976       /* Re-generate channel key */
2977       if (!silc_server_create_channel_key(server, channel, 0))
2978         goto out;
2979
2980       /* Send the channel key. This sends it to our local clients and if
2981          we are normal server to our router as well. */
2982       silc_server_send_channel_key(server, NULL, channel,
2983                                    server->server_type == SILC_ROUTER ?
2984                                    FALSE : !server->standalone);
2985
2986       cipher = (char *)silc_cipher_get_name(channel->send_key);
2987       hmac = (char *)silc_hmac_get_name(channel->hmac);
2988     }
2989   }
2990
2991   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2992     /* User limit is set on channel */
2993     SilcUInt32 user_limit;
2994
2995     /* Get user limit */
2996     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2997     if (!tmp) {
2998       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2999         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3000                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3001         goto out;
3002       }
3003     } else {
3004       SILC_GET32_MSB(user_limit, tmp);
3005       channel->user_limit = user_limit;
3006     }
3007   } else {
3008     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3009       /* User limit mode is unset. Remove user limit */
3010       channel->user_limit = 0;
3011   }
3012
3013   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3014     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3015       /* Passphrase has been set to channel */
3016
3017       /* Get the passphrase */
3018       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3019       if (!tmp) {
3020         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3021                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3022         goto out;
3023       }
3024
3025       /* Save the passphrase */
3026       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3027     }
3028   } else {
3029     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3030       /* Passphrase mode is unset. remove the passphrase */
3031       silc_free(channel->passphrase);
3032       channel->passphrase = NULL;
3033     }
3034   }
3035
3036   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3037     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3038       /* Cipher to use protect the traffic */
3039       SilcCipher send_key, receive_key, olds, oldr;
3040
3041       /* Get cipher */
3042       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3043       if (!cipher) {
3044         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3045                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3046         goto out;
3047       }
3048
3049       /* Delete old cipher and allocate the new one */
3050       if (!silc_cipher_alloc(cipher, &send_key)) {
3051         silc_server_command_send_status_data(
3052                                          cmd, SILC_COMMAND_CMODE,
3053                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3054                                          2, cipher, strlen(cipher));
3055         goto out;
3056       }
3057       if (!silc_cipher_alloc(cipher, &receive_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
3065       olds = channel->send_key;
3066       oldr = channel->receive_key;
3067       channel->send_key = send_key;
3068       channel->receive_key = receive_key;
3069
3070       /* Re-generate channel key */
3071       if (!silc_server_create_channel_key(server, channel, 0)) {
3072         /* We don't have new key, revert to old one */
3073         channel->send_key = olds;
3074         channel->receive_key = oldr;
3075         goto out;
3076       }
3077
3078       /* Remove old channel key for good */
3079       silc_cipher_free(olds);
3080       silc_cipher_free(oldr);
3081
3082       /* Send the channel key. This sends it to our local clients and if
3083          we are normal server to our router as well. */
3084       silc_server_send_channel_key(server, NULL, channel,
3085                                    server->server_type == SILC_ROUTER ?
3086                                    FALSE : !server->standalone);
3087     }
3088   } else {
3089     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3090       /* Cipher mode is unset. Remove the cipher and revert back to
3091          default cipher */
3092       SilcCipher send_key, receive_key, olds, oldr;
3093       cipher = channel->cipher;
3094
3095       /* Delete old cipher and allocate default one */
3096       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3097                              &send_key)) {
3098         silc_server_command_send_status_data(
3099                                       cmd, SILC_COMMAND_CMODE,
3100                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3101                                       2, cipher, strlen(cipher));
3102         goto out;
3103       }
3104       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3105                              &receive_key)) {
3106         silc_server_command_send_status_data(
3107                                       cmd, SILC_COMMAND_CMODE,
3108                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3109                                       2, cipher, strlen(cipher));
3110         goto out;
3111       }
3112
3113       olds = channel->send_key;
3114       oldr = channel->receive_key;
3115       channel->send_key = send_key;
3116       channel->receive_key = receive_key;
3117
3118       /* Re-generate channel key */
3119       if (!silc_server_create_channel_key(server, channel, 0)) {
3120         /* We don't have new key, revert to old one */
3121         channel->send_key = olds;
3122         channel->receive_key = oldr;
3123         goto out;
3124       }
3125
3126       /* Remove old channel key for good */
3127       silc_cipher_free(olds);
3128       silc_cipher_free(oldr);
3129
3130       /* Send the channel key. This sends it to our local clients and if
3131          we are normal server to our router as well. */
3132       silc_server_send_channel_key(server, NULL, channel,
3133                                    server->server_type == SILC_ROUTER ?
3134                                    FALSE : !server->standalone);
3135     }
3136   }
3137
3138   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3139     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3140       /* HMAC to use protect the traffic */
3141       unsigned char hash[SILC_HASH_MAXLEN];
3142       SilcHmac newhmac;
3143
3144       /* Get hmac */
3145       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3146       if (!hmac) {
3147         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3148                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3149         goto out;
3150       }
3151
3152       /* Delete old hmac and allocate the new one */
3153       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3154         silc_server_command_send_status_data(
3155                                         cmd, SILC_COMMAND_CMODE,
3156                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3157                                         2, hmac, strlen(hmac));
3158         goto out;
3159       }
3160
3161       silc_hmac_free(channel->hmac);
3162       channel->hmac = newhmac;
3163
3164       /* Set the HMAC key out of current channel key. The client must do
3165          this locally. */
3166       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3167                      channel->key_len / 8, hash);
3168       silc_hmac_set_key(channel->hmac, hash,
3169                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3170       memset(hash, 0, sizeof(hash));
3171     }
3172   } else {
3173     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3174       /* Hmac mode is unset. Remove the hmac and revert back to
3175          default hmac */
3176       SilcHmac newhmac;
3177       unsigned char hash[SILC_HASH_MAXLEN];
3178       hmac = channel->hmac_name;
3179
3180       /* Delete old hmac and allocate default one */
3181       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3182         silc_server_command_send_status_data(
3183                                         cmd, SILC_COMMAND_CMODE,
3184                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3185                                         2, hmac, strlen(hmac));
3186         goto out;
3187       }
3188
3189       silc_hmac_free(channel->hmac);
3190       channel->hmac = newhmac;
3191
3192       /* Set the HMAC key out of current channel key. The client must do
3193          this locally. */
3194       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3195                      channel->key_len / 8,
3196                      hash);
3197       silc_hmac_set_key(channel->hmac, hash,
3198                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3199       memset(hash, 0, sizeof(hash));
3200     }
3201   }
3202
3203   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3204     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3205       /* Check if the founder public key was received */
3206       founder_key = idata->public_key;
3207       tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3208       if (tmp) {
3209         if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3210           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3211                                                 SILC_STATUS_ERR_AUTH_FAILED,
3212                                                 0);
3213           goto out;
3214         }
3215       } else {
3216         /* If key was not sent and the channel mode has already founder
3217            then the key was not to be changed. */
3218         if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3219           goto has_founder;
3220       }
3221
3222       /* Set the founder authentication */
3223       tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3224       if (!tmp) {
3225         silc_server_command_send_status_reply(
3226                                      cmd, SILC_COMMAND_CMODE,
3227                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3228         goto out;
3229       }
3230
3231       /* Verify the payload before setting the mode */
3232       if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3233                                  founder_key, 0, server->sha1hash,
3234                                  client->id, SILC_ID_CLIENT)) {
3235         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3236                                               SILC_STATUS_ERR_AUTH_FAILED,
3237                                               0);
3238         goto out;
3239       }
3240
3241       /* Save the public key */
3242       if (channel->founder_key)
3243         silc_pkcs_public_key_free(channel->founder_key);
3244       if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3245         channel->founder_key = founder_key;
3246       else
3247         channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3248       if (!channel->founder_key) {
3249         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3250                                               SILC_STATUS_ERR_AUTH_FAILED,
3251                                               0);
3252         goto out;
3253       }
3254
3255       fkey = silc_public_key_payload_encode(channel->founder_key);
3256       if (!fkey) {
3257         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3258                                               SILC_STATUS_ERR_AUTH_FAILED,
3259                                               0);
3260         silc_pkcs_public_key_free(channel->founder_key);
3261         channel->founder_key = NULL;
3262         goto out;
3263       }
3264     }
3265   } else {
3266     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3267       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3268         if (channel->founder_key)
3269           silc_pkcs_public_key_free(channel->founder_key);
3270         channel->founder_key = NULL;
3271       }
3272     }
3273   }
3274  has_founder:
3275
3276   if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3277     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3278       SilcStatus st;
3279
3280       chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3281
3282       if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3283         goto has_pk_list;
3284
3285       set_chpk = TRUE;
3286
3287       /* Process the channel public key(s) */
3288       st = silc_server_set_channel_pk_list(server, NULL, channel,
3289                                            chpkdata, chpklen);
3290       if (st != SILC_STATUS_OK) {
3291         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3292         goto out;
3293       }
3294     }
3295   } else {
3296     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3297       if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3298         if (channel->channel_pubkeys)
3299           silc_hash_table_free(channel->channel_pubkeys);
3300         channel->channel_pubkeys = NULL;
3301         set_chpk = TRUE;
3302       }
3303     }
3304   }
3305  has_pk_list:
3306
3307   /* Finally, set the mode */
3308   old_mask = channel->mode = mode_mask;
3309
3310   /* Send CMODE_CHANGE notify. */
3311   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3312   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3313     SILC_PUT32_MSB(channel->user_limit, ulimit);
3314   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3315                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3316                                      cidp->data, silc_buffer_len(cidp),
3317                                      tmp_mask, 4,
3318                                      cipher, cipher ? strlen(cipher) : 0,
3319                                      hmac, hmac ? strlen(hmac) : 0,
3320                                      passphrase, passphrase ?
3321                                      strlen(passphrase) : 0,
3322                                      fkey ? fkey->data : NULL,
3323                                      fkey ? silc_buffer_len(fkey) : 0,
3324                                      chpkdata ? chpkdata : NULL,
3325                                      chpkdata ? chpklen : 0,
3326                                      mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3327                                      ulimit : NULL,
3328                                      mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3329                                      sizeof(ulimit) : 0);
3330
3331   /* Set CMODE notify type to network */
3332   if (chpkdata && chpklen)
3333     silc_buffer_set(&chpk, chpkdata, chpklen);
3334   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3335                                 SILC_BROADCAST(server), channel,
3336                                 mode_mask, client->id, SILC_ID_CLIENT,
3337                                 cipher, hmac, passphrase, founder_key,
3338                                 chpkdata ? &chpk : NULL);
3339
3340   if (set_chpk)
3341     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3342
3343   /* Send command reply to sender */
3344   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3345   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3346                                  SILC_STATUS_OK, 0, ident, 5,
3347                                  2, tmp_id, tmp_len2,
3348                                  3, tmp_mask, 4,
3349                                  4, fkey ? fkey->data : NULL,
3350                                  fkey ? silc_buffer_len(fkey) : 0,
3351                                  5, chpklist ? chpklist->data :
3352                                  NULL, chpklist ? silc_buffer_len(chpklist)
3353                                  : 0,
3354                                  6, (mode_mask &
3355                                      SILC_CHANNEL_MODE_ULIMIT ?
3356                                      ulimit : NULL),
3357                                  (mode_mask &
3358                                   SILC_CHANNEL_MODE_ULIMIT ?
3359                                   sizeof(ulimit) : 0));
3360   silc_buffer_free(cidp);
3361
3362  out:
3363   channel->mode = old_mask;
3364   silc_buffer_free(chpklist);
3365   silc_buffer_free(fkey);
3366   silc_server_command_free(cmd);
3367 }
3368
3369 /* Server side of CUMODE command. Changes client's mode on a channel. */
3370
3371 SILC_SERVER_CMD_FUNC(cumode)
3372 {
3373   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3374   SilcServer server = cmd->server;
3375   SilcClientEntry client = silc_packet_get_context(cmd->sock);
3376   SilcID id, id2;
3377   SilcChannelEntry channel;
3378   SilcClientEntry target_client;
3379   SilcChannelClientEntry chl;
3380   SilcBuffer idp;
3381   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3382   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3383   int notify = FALSE;
3384   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3385   SilcPublicKey founder_key = NULL;
3386   SilcBuffer fkey = NULL;
3387
3388   if (!client)
3389     goto out;
3390
3391   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3392
3393   /* Get Channel ID */
3394   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3395     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3396                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3397     goto out;
3398   }
3399
3400   /* Get channel entry */
3401   channel = silc_idlist_find_channel_by_id(server->local_list,
3402                                            SILC_ID_GET_ID(id), NULL);
3403   if (!channel) {
3404     channel = silc_idlist_find_channel_by_id(server->global_list,
3405                                              SILC_ID_GET_ID(id), NULL);
3406     if (!channel) {
3407       tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3408       silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3409                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3410                                            0, 2, tmp_ch_id, tmp_ch_len);
3411       goto out;
3412     }
3413   }
3414
3415   /* Check whether sender is on the channel */
3416   if (!silc_server_client_on_channel(client, channel, &chl)) {
3417     tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3418     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3419                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3420                                          2, tmp_ch_id, tmp_ch_len);
3421     goto out;
3422   }
3423   sender_mask = chl->mode;
3424
3425   /* Get the target client's channel mode mask */
3426   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3427   if (!tmp_mask) {
3428     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3429                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3430                                           0);
3431     goto out;
3432   }
3433   SILC_GET32_MSB(target_mask, tmp_mask);
3434
3435   /* Get target Client ID */
3436   if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
3437     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3438                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3439     goto out;
3440   }
3441
3442   /* Get target client's entry */
3443   target_client = silc_idlist_find_client_by_id(server->local_list,
3444                                                 SILC_ID_GET_ID(id2),
3445                                                 TRUE, NULL);
3446   if (!target_client)
3447     target_client = silc_idlist_find_client_by_id(server->global_list,
3448                                                   SILC_ID_GET_ID(id2),
3449                                                   TRUE, NULL);
3450
3451   if (target_client != client &&
3452       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3453       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3454     tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3455     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3456                                          SILC_STATUS_ERR_NOT_YOU, 0,
3457                                          2, tmp_ch_id, tmp_ch_len);
3458     goto out;
3459   }
3460
3461   /* Check whether target client is on the channel */
3462   if (target_client != client) {
3463     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3464       tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3465       tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3466       silc_server_command_send_status_data2(
3467                                   cmd, SILC_COMMAND_CUMODE,
3468                                   SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3469                                   2, tmp_id, tmp_len,
3470                                   3, tmp_ch_id, tmp_ch_len);
3471       goto out;
3472     }
3473   }
3474
3475   /*
3476    * Change the mode
3477    */
3478
3479   /* If the target client is founder, no one else can change their mode
3480      but themselves. */
3481   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3482     tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3483     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3484                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3485                                          0, 2, tmp_ch_id, tmp_ch_len);
3486     goto out;
3487   }
3488
3489   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3490     if (target_client != client) {
3491       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3492                                             SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3493                                             0);
3494       goto out;
3495     }
3496
3497     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3498       /* The client tries to claim the founder rights. */
3499       unsigned char *tmp_auth;
3500       SilcUInt32 tmp_auth_len;
3501       SilcChannelClientEntry chl2;
3502       SilcHashTableList htl;
3503
3504       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3505           !channel->founder_key) {
3506         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3507                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3508         goto out;
3509       }
3510
3511       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3512       if (!tmp_auth) {
3513         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3514                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3515         goto out;
3516       }
3517
3518       /* Verify the authentication payload */
3519       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3520                                  channel->founder_key, 0, server->sha1hash,
3521                                  client->id, SILC_ID_CLIENT)) {
3522         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3523                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3524         goto out;
3525       }
3526
3527       notify = TRUE;
3528       founder_key = channel->founder_key;
3529       fkey = silc_public_key_payload_encode(founder_key);
3530       if (!fkey) {
3531         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3532                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3533         goto out;
3534       }
3535
3536       /* There cannot be anyone else as founder on the channel now.  This
3537          client is definitely the founder due to this authentication.  This
3538          is done only on router, not on server, since server cannot know
3539          whether router will accept this mode change or not.  XXX This
3540          probably shouldn't be done anymore at all, may cause problems in
3541          router-router connections too (maybe just AUTH_FAILED error should
3542          be returned). -Pekka */
3543       if (server->server_type == SILC_ROUTER) {
3544         silc_hash_table_list(channel->user_list, &htl);
3545         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3546           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3547             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3548             silc_server_force_cumode_change(server, NULL, channel, chl2,
3549                                             chl2->mode);
3550             break;
3551           }
3552         silc_hash_table_list_reset(&htl);
3553       }
3554
3555       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3556     }
3557   } else {
3558     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3559       if (target_client == client) {
3560         /* Remove channel founder rights from itself */
3561         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3562         notify = TRUE;
3563       } else {
3564         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3565                                               SILC_STATUS_ERR_NOT_YOU, 0);
3566         goto out;
3567       }
3568     }
3569   }
3570
3571   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3572     /* Promote to operator */
3573     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3574       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3575           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3576         tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3577         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3578                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3579                                              0, 2, tmp_ch_id, tmp_ch_len);
3580         goto out;
3581       }
3582
3583       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3584       notify = TRUE;
3585     }
3586   } else {
3587     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3588       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3589           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3590         tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3591         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3592                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3593                                              0, 2, tmp_ch_id, tmp_ch_len);
3594         goto out;
3595       }
3596
3597       /* Demote to normal user */
3598       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3599       notify = TRUE;
3600     }
3601   }
3602
3603   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3604     if (target_client != client) {
3605       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3606                                             SILC_STATUS_ERR_NOT_YOU, 0);
3607       goto out;
3608     }
3609
3610     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3611       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3612       notify = TRUE;
3613     }
3614   } else {
3615     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3616       if (target_client != client) {
3617         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3618                                               SILC_STATUS_ERR_NOT_YOU, 0);
3619         goto out;
3620       }
3621
3622       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3623       notify = TRUE;
3624     }
3625   }
3626
3627   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3628     if (target_client != client) {
3629       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3630                                             SILC_STATUS_ERR_NOT_YOU, 0);
3631       goto out;
3632     }
3633
3634     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3635       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3636       notify = TRUE;
3637     }
3638   } else {
3639     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3640       if (target_client != client) {
3641         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3642                                               SILC_STATUS_ERR_NOT_YOU, 0);
3643         goto out;
3644       }
3645
3646       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3647       notify = TRUE;
3648     }
3649   }
3650
3651   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3652     if (target_client != client) {
3653       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3654                                             SILC_STATUS_ERR_NOT_YOU, 0);
3655       goto out;
3656     }
3657
3658     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3659       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3660       notify = TRUE;
3661     }
3662   } else {
3663     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3664       if (target_client != client) {
3665         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3666                                               SILC_STATUS_ERR_NOT_YOU, 0);
3667         goto out;
3668       }
3669
3670       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3671       notify = TRUE;
3672     }
3673   }
3674
3675   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3676     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3677       if (client == target_client) {
3678         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3679                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3680         goto out;
3681       }
3682       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3683       notify = TRUE;
3684     }
3685   } else {
3686     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3687       if (client == target_client) {
3688         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3689                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3690         goto out;
3691       }
3692       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3693       notify = TRUE;
3694     }
3695   }
3696
3697   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3698   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3699   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3700
3701   /* Send notify to channel, notify only if mode was actually changed. */
3702   if (notify) {
3703     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3704                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3705                                        idp->data, silc_buffer_len(idp),
3706                                        tmp_mask, 4,
3707                                        tmp_id, tmp_len,
3708                                        fkey ? fkey->data : NULL,
3709                                        fkey ? silc_buffer_len(fkey) : 0);
3710
3711     /* Set CUMODE notify type to network */
3712     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3713                                    SILC_BROADCAST(server), channel,
3714                                    target_mask, client->id, SILC_ID_CLIENT,
3715                                    target_client->id, founder_key);
3716   }
3717
3718   /* Send command reply to sender */
3719   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3720                                  SILC_STATUS_OK, 0, ident, 3,
3721                                  2, tmp_mask, 4,
3722                                  3, tmp_ch_id, tmp_ch_len,
3723                                  4, tmp_id, tmp_len);
3724   silc_buffer_free(idp);
3725
3726  out:
3727   silc_buffer_free(fkey);
3728   silc_server_command_free(cmd);
3729 }
3730
3731 /* Server side of KICK command. Kicks client out of channel. */
3732
3733 SILC_SERVER_CMD_FUNC(kick)
3734 {
3735   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3736   SilcServer server = cmd->server;
3737   SilcClientEntry client = silc_packet_get_context(cmd->sock);
3738   SilcClientEntry target_client;
3739   SilcID id, id2;
3740   SilcChannelEntry channel;
3741   SilcChannelClientEntry chl;
3742   SilcBuffer idp;
3743   SilcUInt32 tmp_len, target_idp_len, clen;
3744   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3745   unsigned char *tmp, *comment, *target_idp;
3746
3747   if (!client)
3748     goto out;
3749
3750   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3751
3752   /* Get Channel ID */
3753   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3754     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3755                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3756     goto out;
3757   }
3758
3759   /* Get channel entry */
3760   channel = silc_idlist_find_channel_by_id(server->local_list,
3761                                            SILC_ID_GET_ID(id), NULL);
3762   if (!channel) {
3763     channel = silc_idlist_find_channel_by_id(server->local_list,
3764                                              SILC_ID_GET_ID(id), NULL);
3765     if (!channel) {
3766       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3767       silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3768                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3769                                            0, 2, tmp, tmp_len);
3770       goto out;
3771     }
3772   }
3773
3774   /* Check whether sender is on the channel */
3775   if (!silc_server_client_on_channel(client, channel, &chl)) {
3776     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3777     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3778                                          SILC_STATUS_ERR_NOT_ON_CHANNEL,
3779                                          0, 2, tmp, tmp_len);
3780     goto out;
3781   }
3782
3783   /* Check that the kicker is channel operator or channel founder */
3784   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3785       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3786     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3787     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3788                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3789                                          0, 2, tmp, tmp_len);
3790     goto out;
3791   }
3792
3793   /* Get target Client ID */
3794   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
3795     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3796                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3797     goto out;
3798   }
3799
3800   /* Get target client's entry */
3801   target_client = silc_idlist_find_client_by_id(server->local_list,
3802                                                 SILC_ID_GET_ID(id2),
3803                                                 TRUE, NULL);
3804   if (!target_client)
3805     target_client = silc_idlist_find_client_by_id(server->global_list,
3806                                                   SILC_ID_GET_ID(id2),
3807                                                   TRUE, NULL);
3808
3809   /* Check whether target client is on the channel */
3810   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3811     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3812     target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3813     silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3814                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3815                                           0, 2, target_idp, target_idp_len,
3816                                           3, tmp, tmp_len);
3817     goto out;
3818   }
3819
3820   /* Check that the target client is not channel founder. Channel founder
3821      cannot be kicked from the channel. */
3822   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3823     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3824     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3825                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3826                                          0, 2, tmp, tmp_len);
3827     goto out;
3828   }
3829
3830   /* Get comment */
3831   comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3832   if (clen > 128)
3833     comment = NULL;
3834
3835   /* Send the reply back to the client */
3836   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3837   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3838   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3839                                  SILC_STATUS_OK, 0, ident, 2,
3840                                  2, tmp, tmp_len,
3841                                  3, target_idp, target_idp_len);
3842
3843   /* Send KICKED notify to local clients on the channel */
3844   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3845   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3846                                      SILC_NOTIFY_TYPE_KICKED, 3,
3847                                      target_idp, target_idp_len,
3848                                      comment, comment ? strlen(comment) : 0,
3849                                      idp->data, silc_buffer_len(idp));
3850   silc_buffer_free(idp);
3851
3852   /* Send KICKED notify to primary route */
3853   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3854                                  SILC_BROADCAST(server), channel,
3855                                  target_client->id, client->id, comment);
3856
3857   /* Remove the client from channel's invite list */
3858   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3859     SilcBuffer ab =
3860       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3861     SilcArgumentPayload args =
3862       silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
3863
3864     silc_server_inviteban_process(server, channel->invite_list, 1, args);
3865     silc_buffer_free(ab);
3866     silc_argument_payload_free(args);
3867   }
3868
3869   /* Remove the client from the channel. If the channel does not exist
3870      after removing the client then the client kicked itself off the channel
3871      and we don't have to send anything after that. */
3872   if (!silc_server_remove_from_one_channel(server, NULL, channel,
3873                                            target_client, FALSE))
3874     goto out;
3875
3876   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3877     /* Re-generate channel key */
3878     if (!silc_server_create_channel_key(server, channel, 0))
3879       goto out;
3880
3881     /* Send the channel key to the channel. The key of course is not sent
3882        to the client who was kicked off the channel. */
3883     silc_server_send_channel_key(server, target_client->connection, channel,
3884                                  server->server_type == SILC_ROUTER ?
3885                                  FALSE : !server->standalone);
3886   }
3887
3888  out:
3889   silc_server_command_free(cmd);
3890 }
3891
3892 /* Server side of OPER command. Client uses this comand to obtain server
3893    operator privileges to this server/router. */
3894
3895 SILC_SERVER_CMD_FUNC(oper)
3896 {
3897   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3898   SilcServer server = cmd->server;
3899   SilcClientEntry client = silc_packet_get_context(cmd->sock);
3900   unsigned char *username = NULL, *auth;
3901   SilcUInt32 tmp_len;
3902   SilcServerConfigAdmin *admin;
3903   SilcIDListData idata = (SilcIDListData)client;
3904   SilcBool result = FALSE;
3905   SilcPublicKey cached_key;
3906   const char *hostname, *ip;
3907
3908   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
3909     goto out;
3910
3911   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3912
3913   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
3914                               NULL, &hostname, &ip, NULL);
3915
3916   /* Get the username */
3917   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3918   if (!username) {
3919     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3920                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3921                                           0);
3922     goto out;
3923   }
3924
3925   /* Check username */
3926   username = silc_identifier_check(username, strlen(username),
3927                                    SILC_STRING_UTF8, 128, &tmp_len);
3928   if (!username) {
3929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3930                                           SILC_STATUS_ERR_BAD_USERNAME,
3931                                           0);
3932     goto out;
3933   }
3934
3935   /* Get the admin configuration */
3936   admin = silc_server_config_find_admin(server, (char *)ip,
3937                                         username, client->nickname);
3938   if (!admin) {
3939     admin = silc_server_config_find_admin(server, (char *)hostname,
3940                                           username, client->nickname);
3941     if (!admin) {
3942       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3943                                             SILC_STATUS_ERR_AUTH_FAILED,
3944                                             0);
3945       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3946                      "nickname '%s' from %s", username,
3947                      client->nickname, hostname));
3948       goto out;
3949     }
3950   }
3951
3952   /* Get the authentication payload */
3953   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3954   if (!auth) {
3955     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3956                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3957                                           0);
3958     goto out;
3959   }
3960
3961   /* Verify the authentication data. If both passphrase and public key
3962      is set then try both of them. */
3963   if (admin->passphrase)
3964     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3965                                    admin->passphrase, admin->passphrase_len,
3966                                    idata->hash, client->id, SILC_ID_CLIENT);
3967   if (!result && admin->publickeys) {
3968     cached_key =
3969       silc_server_get_public_key(server,
3970                                  SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
3971     if (!cached_key)
3972       goto out;
3973     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3974                                    cached_key, 0, idata->hash,
3975                                    client->id, SILC_ID_CLIENT);
3976   }
3977   if (!result) {
3978     /* Authentication failed */
3979     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3980                                           SILC_STATUS_ERR_AUTH_FAILED,
3981                                           0);
3982     goto out;
3983   }
3984
3985   /* Client is now server operator */
3986   client->mode |= SILC_UMODE_SERVER_OPERATOR;
3987
3988   /* Update statistics */
3989   if (SILC_IS_LOCAL(client))
3990     server->stat.my_server_ops++;
3991   if (server->server_type == SILC_ROUTER)
3992     server->stat.server_ops++;
3993
3994   /* Send UMODE change to primary router */
3995   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3996                                 SILC_BROADCAST(server), client->id,
3997                                 client->mode);
3998
3999   /* Check if anyone is watching this nickname */
4000   if (server->server_type == SILC_ROUTER)
4001     silc_server_check_watcher_list(server, client, NULL,
4002                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4003
4004   /* Send reply to the sender */
4005   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4006                                         SILC_STATUS_OK, 0);
4007
4008  out:
4009   silc_free(username);
4010   silc_server_command_free(cmd);
4011 }
4012
4013 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4014 {
4015   SilcServer server = app_context;
4016   QuitInternal q = (QuitInternal)context;
4017   SilcClientID *client_id = (SilcClientID *)q->sock;
4018   SilcClientEntry client;
4019   SilcPacketStream sock;
4020
4021   client = silc_idlist_find_client_by_id(server->local_list, client_id,
4022                                          TRUE, NULL);
4023   if (client && client->connection) {
4024     sock = client->connection;
4025
4026     /* Close the connection on our side */
4027     client->router = NULL;
4028     client->connection = NULL;
4029     silc_server_close_connection(server, sock);
4030   }
4031
4032   silc_free(client_id);
4033   silc_free(q);
4034 }
4035
4036 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4037 {
4038   SilcServer server = app_context;
4039   QuitInternal q = (QuitInternal)context;
4040   SilcClientID *client_id = (SilcClientID *)q->sock;
4041   SilcClientEntry client;
4042
4043   client = silc_idlist_find_client_by_id(server->local_list, client_id,
4044                                          TRUE, NULL);
4045   if (client && client->mode & SILC_UMODE_DETACHED) {
4046     SILC_LOG_DEBUG(("Detach timeout"));
4047     silc_server_free_client_data(server, NULL, client, TRUE,
4048                                  "Detach timeout");
4049   }
4050
4051   silc_free(client_id);
4052   silc_free(q);
4053 }
4054
4055 /* Server side of DETACH command.  Detached the client from the network
4056    by closing the connection but preserving the session. */
4057
4058 SILC_SERVER_CMD_FUNC(detach)
4059 {
4060   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4061   SilcServer server = cmd->server;
4062   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4063   QuitInternal q;
4064
4065   if (server->config->detach_disabled) {
4066     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4067                                           SILC_STATUS_ERR_OPERATION_ALLOWED,
4068                                           0);
4069     goto out;
4070   }
4071
4072   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4073     goto out;
4074
4075   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4076
4077   /* Remove operator privileges, since the client may resume in some
4078      other server which to it does not have operator privileges. */
4079   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4080   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4081
4082   /* Send the user mode notify to notify that client is detached */
4083   client->mode |= SILC_UMODE_DETACHED;
4084   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4085   client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4086   client->last_command = 0;
4087   client->fast_command = 0;
4088   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4089                                 SILC_BROADCAST(server), client->id,
4090                                 client->mode);
4091   server->stat.my_detached++;
4092
4093   /* Check if anyone is watching this nickname */
4094   if (server->server_type == SILC_ROUTER)
4095     silc_server_check_watcher_list(server, client, NULL,
4096                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4097
4098   q = silc_calloc(1, sizeof(*q));
4099   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4100   silc_schedule_task_add_timeout(server->schedule,
4101                                  silc_server_command_detach_cb,
4102                                  q, 0, 200000);
4103
4104   if (server->config->detach_timeout) {
4105     q = silc_calloc(1, sizeof(*q));
4106     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4107     silc_schedule_task_add_timeout(server->schedule,
4108                                    silc_server_command_detach_timeout,
4109                                    q, server->config->detach_timeout * 60, 0);
4110   }
4111
4112   /* Send reply to the sender */
4113   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4114                                         SILC_STATUS_OK, 0);
4115
4116  out:
4117   silc_server_command_free(cmd);
4118 }
4119
4120 /* Server side of WATCH command. */
4121
4122 SILC_SERVER_CMD_FUNC(watch)
4123 {
4124   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4125   SilcServer server = cmd->server;
4126   char *add_nick, *del_nick;
4127   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4128   unsigned char hash[SILC_HASH_MAXLEN], *tmp,  *pk, *nick;
4129   SilcClientEntry client;
4130   SilcID id;
4131   SilcUInt16 old_ident;
4132
4133   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4134
4135   if (server->server_type != SILC_ROUTER && !server->standalone) {
4136     if (!cmd->pending) {
4137       /* Send the command to router */
4138       SilcBuffer tmpbuf;
4139
4140       /* If backup receives this from primary, handle it locally */
4141       if (server->server_type == SILC_BACKUP_ROUTER &&
4142           cmd->sock == SILC_PRIMARY_ROUTE(server))
4143         goto process_watch;
4144
4145       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4146
4147       /* Statistics */
4148       cmd->server->stat.commands_sent++;
4149
4150       old_ident = silc_command_get_ident(cmd->payload);
4151       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4152       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4153
4154       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4155                               SILC_PACKET_COMMAND, cmd->packet->flags,
4156                               tmpbuf->data, silc_buffer_len(tmpbuf));
4157
4158       /* Reprocess this packet after received reply from router */
4159       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4160                                   silc_command_get_ident(cmd->payload),
4161                                   silc_server_command_watch,
4162                                   silc_server_command_dup(cmd));
4163       cmd->pending = TRUE;
4164       silc_command_set_ident(cmd->payload, old_ident);
4165       silc_buffer_free(tmpbuf);
4166       goto out;
4167     } else {
4168       SilcServerCommandReplyContext reply = context2;
4169       SilcStatus status;
4170
4171       if (!reply)
4172         goto out;
4173
4174       silc_command_get_status(reply->payload, &status, NULL);
4175
4176       /* Backup router handles the WATCH command also. */
4177       if (server->server_type != SILC_BACKUP_ROUTER ||
4178           SILC_STATUS_IS_ERROR(status)) {
4179         /* Received reply from router, just send same data to the client. */
4180         SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4181         silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4182                                               0);
4183         goto out;
4184       }
4185     }
4186   }
4187
4188   /* We are router and keep the watch list for local cell */
4189  process_watch:
4190
4191   /* Get the client ID */
4192   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4193     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4194                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4195                                           0);
4196     goto out;
4197   }
4198
4199   /* Get the client entry which must be in local list */
4200   client = silc_idlist_find_client_by_id(server->local_list,
4201                                          SILC_ID_GET_ID(id), TRUE, NULL);
4202   if (!client) {
4203     /* Backup checks global list also */
4204     if (server->server_type == SILC_BACKUP_ROUTER)
4205       client = silc_idlist_find_client_by_id(server->global_list,
4206                                              SILC_ID_GET_ID(id), TRUE, NULL);
4207     if (!client) {
4208       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4209       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4210                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4211                                            0, 2, tmp, tmp_len);
4212       goto out;
4213     }
4214   }
4215
4216   /* Take public key for watching by public key */
4217   pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4218
4219   /* Take nickname */
4220   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4221   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4222   if (!add_nick && !del_nick && !pk) {
4223     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4224                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4225                                           0);
4226     goto out;
4227   }
4228
4229   if (add_nick && add_nick_len > 128) {
4230     add_nick_len = 128;
4231     add_nick[add_nick_len - 1] = '\0';
4232   }
4233   if (del_nick && del_nick_len > 128) {
4234     del_nick_len = 128;
4235     del_nick[del_nick_len - 1] = '\0';
4236   }
4237
4238   /* Add new nickname to be watched in our cell */
4239   if (add_nick) {
4240     nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4241                                  &add_nick_len);
4242     if (!nick) {
4243       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4244                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4245       goto out;
4246     }
4247
4248     /* Hash the nick, we have the hash saved, not nicks because we can
4249        do one to one mapping to the nick from Client ID hash this way. */
4250     silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4251
4252     /* Check whether this client is already watching this nickname */
4253     if (silc_hash_table_find_by_context(server->watcher_list, hash,
4254                                         client, NULL)) {
4255       /* Nickname is alredy being watched for this client */
4256       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4257                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
4258                                             0);
4259       silc_free(nick);
4260       goto out;
4261     }
4262
4263     /* Get the nickname from the watcher list and use the same key in
4264        new entries as well.  If key doesn't exist then create it. */
4265     if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4266       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4267
4268     /* Add the client to the watcher list with the specified nickname hash. */
4269     silc_hash_table_add(server->watcher_list, tmp, client);
4270     silc_free(nick);
4271   }
4272
4273   /* Delete nickname from watch list */
4274   if (del_nick) {
4275     nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4276                                  &del_nick_len);
4277     if (!nick) {
4278       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4279                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4280       goto out;
4281     }
4282
4283     /* Hash the nick, we have the hash saved, not nicks because we can
4284        do one to one mapping to the nick from Client ID hash this way. */
4285     silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4286
4287     /* Check that this client is watching for this nickname */
4288     if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4289                                          client, (void *)&tmp)) {
4290       /* Nickname is alredy being watched for this client */
4291       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4292                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4293                                            2, nick, del_nick_len);
4294       silc_free(nick);
4295       goto out;
4296     }
4297
4298     /* Delete the nickname from the watcher list. */
4299     silc_hash_table_del_by_context(server->watcher_list, hash, client);
4300
4301     /* Now check whether there still exists entries with this key, if not
4302        then free the key to not leak memory. */
4303     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4304       silc_free(tmp);
4305     silc_free(nick);
4306   }
4307
4308   /* Add/del public key */
4309   if (pk) {
4310     SilcUInt16 pkargc;
4311     SilcArgumentPayload pkargs;
4312     SilcUInt32 type;
4313     SilcPublicKey public_key, pkkey;
4314
4315     if (pk_len < 2) {
4316       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4317                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4318                                             0);
4319       goto out;
4320     }
4321
4322     /* Get the argument from the Argument List Payload */
4323     SILC_GET16_MSB(pkargc, pk);
4324     pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4325     if (!pkargs) {
4326       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4327                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4328                                             0);
4329       goto out;
4330     }
4331
4332     pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4333     while (pk) {
4334       if (!silc_public_key_payload_decode(pk, pk_len, &public_key))
4335         continue;
4336       if (type == 0x03)
4337         type = 0x00;
4338
4339       if (type == 0x00) {
4340         /* Add public key to watch list */
4341
4342         /* Check whether this client is already watching this public key */
4343         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4344                                             public_key, client, NULL)) {
4345           silc_pkcs_public_key_free(public_key);
4346           silc_server_command_send_status_reply(
4347                                 cmd, SILC_COMMAND_WATCH,
4348                                 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4349           goto out;
4350         }
4351
4352         /* Get the public key from the watcher list and use the same key in
4353            new entries as well.  If key doesn't exist then create it. */
4354         pkkey = NULL;
4355         if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4356                                   (void *)&pkkey, NULL))
4357           pkkey = public_key;
4358         else
4359           silc_pkcs_public_key_free(public_key);
4360
4361         /* Add the client to the watcher list with the specified public
4362            key. */
4363         silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4364
4365       } else if (type == 0x01) {
4366         /* Delete public key from watch list */
4367
4368         /* Check that this client is watching this public key */
4369         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4370                                             public_key, client,
4371                                             (void *)&pkkey)) {
4372           silc_pkcs_public_key_free(public_key);
4373           silc_server_command_send_status_reply(
4374                                 cmd, SILC_COMMAND_WATCH,
4375                                 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4376           goto out;
4377         }
4378
4379         /* Delete the public key from the watcher list. */
4380         silc_hash_table_del_by_context(server->watcher_list_pk,
4381                                        public_key, client);
4382
4383         /* Now check whether there still exists entries with this key, if
4384            not then free the key to not leak memory. */
4385         if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4386           silc_pkcs_public_key_free(pkkey);
4387         silc_pkcs_public_key_free(public_key);
4388       }
4389
4390       pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4391     }
4392   }
4393
4394   /* Send reply */
4395   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4396                                         SILC_STATUS_OK, 0);
4397
4398   /* Distribute the watch list to backup routers too */
4399   if (server->backup) {
4400     SilcBuffer tmpbuf;
4401
4402     /* Statistics */
4403     cmd->server->stat.commands_sent++;
4404
4405     old_ident = silc_command_get_ident(cmd->payload);
4406     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4407     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4408     silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4409                             SILC_PACKET_COMMAND,
4410                             cmd->packet->flags, tmpbuf->data,
4411                             silc_buffer_len(tmpbuf),
4412                             FALSE, TRUE);
4413     silc_command_set_ident(cmd->payload, old_ident);
4414     silc_buffer_free(tmpbuf);
4415   }
4416
4417  out:
4418   silc_server_command_free(cmd);
4419 }
4420
4421 /* Server side of SILCOPER command. Client uses this comand to obtain router
4422    operator privileges to this router. */
4423
4424 SILC_SERVER_CMD_FUNC(silcoper)
4425 {
4426   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4427   SilcServer server = cmd->server;
4428   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4429   unsigned char *username = NULL, *auth;
4430   SilcUInt32 tmp_len;
4431   SilcServerConfigAdmin *admin;
4432   SilcIDListData idata = (SilcIDListData)client;
4433   SilcBool result = FALSE;
4434   SilcPublicKey cached_key;
4435   const char *hostname, *ip;
4436
4437   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4438     goto out;
4439
4440   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4441
4442   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4443                               NULL, &hostname, &ip, NULL);
4444
4445   if (server->server_type != SILC_ROUTER) {
4446     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4447                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4448     goto out;
4449   }
4450
4451   /* Get the username */
4452   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4453   if (!username) {
4454     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4455                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4456                                           0);
4457     goto out;
4458   }
4459
4460   /* Check username */
4461   username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4462                                    &tmp_len);
4463   if (!username) {
4464     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4465                                           SILC_STATUS_ERR_BAD_USERNAME,
4466                                           0);
4467     goto out;
4468   }
4469
4470   /* Get the admin configuration */
4471   admin = silc_server_config_find_admin(server, (char *)ip,
4472                                         username, client->nickname);
4473   if (!admin) {
4474     admin = silc_server_config_find_admin(server, (char *)hostname,
4475                                           username, client->nickname);
4476     if (!admin) {
4477       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4478                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
4479       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4480                      "nickname '%s' from %s", username,
4481                      client->nickname, hostname));
4482       goto out;
4483     }
4484   }
4485
4486   /* Get the authentication payload */
4487   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4488   if (!auth) {
4489     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4490                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4491                                           0);
4492     goto out;
4493   }
4494
4495   /* Verify the authentication data. If both passphrase and public key
4496      is set then try both of them. */
4497   if (admin->passphrase)
4498     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4499                                    admin->passphrase, admin->passphrase_len,
4500                                    idata->hash, client->id, SILC_ID_CLIENT);
4501   if (!result && admin->publickeys) {
4502     cached_key =
4503       silc_server_get_public_key(server,
4504                                  SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4505     if (!cached_key)
4506       goto out;
4507     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4508                                    cached_key, 0, idata->hash,
4509                                    client->id, SILC_ID_CLIENT);
4510   }
4511   if (!result) {
4512     /* Authentication failed */
4513     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4514                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4515     goto out;
4516   }
4517
4518   /* Client is now router operator */
4519   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4520
4521   /* Update statistics */
4522   if (SILC_IS_LOCAL(client))
4523     server->stat.my_router_ops++;
4524   if (server->server_type == SILC_ROUTER)
4525     server->stat.router_ops++;
4526
4527   /* Send UMODE change to primary router */
4528   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4529                                 SILC_BROADCAST(server), client->id,
4530                                 client->mode);
4531
4532   /* Check if anyone is watching this nickname */
4533   if (server->server_type == SILC_ROUTER)
4534     silc_server_check_watcher_list(server, client, NULL,
4535                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4536
4537   /* Send reply to the sender */
4538   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4539                                         SILC_STATUS_OK, 0);
4540
4541  out:
4542   silc_free(username);
4543   silc_server_command_free(cmd);
4544 }
4545
4546 /* Server side of command BAN. This is used to manage the ban list of the
4547    channel. To add clients and remove clients from the ban list. */
4548
4549 SILC_SERVER_CMD_FUNC(ban)
4550 {
4551   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4552   SilcServer server = cmd->server;
4553   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4554   SilcBuffer list, tmp2;
4555   SilcChannelEntry channel;
4556   SilcChannelClientEntry chl;
4557   SilcID id;
4558   unsigned char *tmp_id, *tmp, *atype = NULL;
4559   SilcUInt32 id_len, len, len2;
4560   SilcArgumentPayload args;
4561   SilcHashTableList htl;
4562   SilcUInt32 type;
4563   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4564   SilcBufferStruct blist;
4565
4566   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4567     goto out;
4568
4569   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4570
4571   /* Get Channel ID */
4572   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4573     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4574                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4575     goto out;
4576   }
4577
4578   /* Get channel entry. The server must know about the channel since the
4579      client is expected to be on the channel. */
4580   channel = silc_idlist_find_channel_by_id(server->local_list,
4581                                            SILC_ID_GET_ID(id), NULL);
4582   if (!channel) {
4583     channel = silc_idlist_find_channel_by_id(server->global_list,
4584                                              SILC_ID_GET_ID(id), NULL);
4585     if (!channel) {
4586       tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4587       silc_server_command_send_status_data(
4588                                            cmd, SILC_COMMAND_BAN,
4589                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4590                                            0, 2, tmp_id, id_len);
4591       goto out;
4592     }
4593   }
4594
4595   /* Check whether this client is on the channel */
4596   if (!silc_server_client_on_channel(client, channel, &chl)) {
4597     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4598     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4599                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4600                                          2, tmp_id, id_len);
4601     goto out;
4602   }
4603
4604   /* The client must be at least channel operator. */
4605   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4606     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4607     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4608                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4609                                          2, tmp_id, id_len);
4610     goto out;
4611   }
4612
4613   /* Get the ban information */
4614   tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4615   if (tmp && len2 > 2) {
4616     /* Parse the arguments to see they are constructed correctly */
4617     SILC_GET16_MSB(argc, tmp);
4618     args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4619     if (!args) {
4620       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4621                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4622                                             0);
4623       goto out;
4624     }
4625
4626     /* Get the type of action */
4627     atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4628     if (atype && len == 1) {
4629       if (atype[0] == 0x00) {
4630         /* Allocate hash table for ban list if it doesn't exist yet */
4631         if (!channel->ban_list)
4632           channel->ban_list =
4633             silc_hash_table_alloc(0, silc_hash_ptr,
4634                                   NULL, NULL, NULL,
4635                                   silc_server_inviteban_destruct, channel,
4636                                   TRUE);
4637
4638         /* Check for resource limit */
4639         if (silc_hash_table_count(channel->ban_list) > 64) {
4640           silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4641                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
4642                                                 0);
4643           goto out;
4644         }
4645       }
4646
4647       /* Now add or delete the information. */
4648       if (!silc_server_inviteban_process(server, channel->ban_list,
4649                                          (SilcUInt8)atype[0], args)) {
4650         silc_server_command_send_status_reply(
4651                                       cmd, SILC_COMMAND_BAN,
4652                                       SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4653                                       0);
4654         goto out;
4655       }
4656     }
4657     silc_argument_payload_free(args);
4658   }
4659
4660   /* Encode ban list */
4661   list = NULL;
4662   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4663     list = silc_buffer_alloc_size(2);
4664     silc_buffer_format(list,
4665                        SILC_STR_UI_SHORT(silc_hash_table_count(
4666                                           channel->ban_list)),
4667                        SILC_STR_END);
4668     silc_hash_table_list(channel->ban_list, &htl);
4669     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4670       list = silc_argument_payload_encode_one(list, tmp2->data,
4671                                               silc_buffer_len(tmp2), type);
4672     silc_hash_table_list_reset(&htl);
4673   }
4674
4675   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4676
4677   /* Send BAN notify type to local servers (but not clients) and to
4678      network. */
4679   if (atype && tmp && len2) {
4680     silc_buffer_set(&blist, tmp, len2);
4681
4682     /* Send to local servers if we are router */
4683     if (server->server_type == SILC_ROUTER)
4684       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4685                                          SILC_NOTIFY_TYPE_BAN, 3,
4686                                          tmp_id, id_len,
4687                                          atype, 1,
4688                                          tmp ? blist.data : NULL,
4689                                          tmp ? silc_buffer_len(&blist) : 0);
4690
4691     /* Send to network. */
4692     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4693                                 SILC_BROADCAST(server), channel, atype,
4694                                 &blist);
4695   }
4696
4697   /* Send the reply back to the client */
4698   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4699                                  SILC_STATUS_OK, 0, ident, 2,
4700                                  2, tmp_id, id_len,
4701                                  3, list ? list->data : NULL,
4702                                  list ? silc_buffer_len(list) : 0);
4703   silc_buffer_free(list);
4704
4705  out:
4706   silc_server_command_free(cmd);
4707 }
4708
4709 /* Server side command of LEAVE. Removes client from a channel. */
4710
4711 SILC_SERVER_CMD_FUNC(leave)
4712 {
4713   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4714   SilcServer server = cmd->server;
4715   SilcPacketStream sock = cmd->sock;
4716   SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4717   SilcID id;
4718   SilcChannelEntry channel;
4719   SilcUInt32 len;
4720   unsigned char *tmp;
4721
4722   if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4723     goto out;
4724
4725   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4726
4727   /* Get Channel ID */
4728   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4729     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4730                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4731     goto out;
4732   }
4733
4734   /* Get channel entry */
4735   channel = silc_idlist_find_channel_by_id(server->local_list,
4736                                            SILC_ID_GET_ID(id), NULL);
4737   if (!channel) {
4738     channel = silc_idlist_find_channel_by_id(server->global_list,
4739                                              SILC_ID_GET_ID(id), NULL);
4740     if (!channel) {
4741       tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4742       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4743                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4744                                            0, 2, tmp, len);
4745       goto out;
4746     }
4747   }
4748
4749   /* Check whether this client is on the channel */
4750   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4751     tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4752     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4753                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4754                                          2, tmp, len);
4755     goto out;
4756   }
4757
4758   /* Notify routers that they should remove this client from their list
4759      of clients on the channel. Send LEAVE notify type. */
4760   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4761                                 SILC_BROADCAST(server), channel, id_entry->id);
4762
4763   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4764   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4765                                        SILC_STATUS_OK, 0, 2, tmp, len);
4766
4767   /* Remove client from channel */
4768   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4769                                            TRUE))
4770     /* If the channel does not exist anymore we won't send anything */
4771     goto out;
4772
4773   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4774     /* Re-generate channel key */
4775     if (!silc_server_create_channel_key(server, channel, 0))
4776       goto out;
4777
4778     /* Send the channel key */
4779     silc_server_send_channel_key(server, NULL, channel,
4780                                  server->server_type == SILC_ROUTER ?
4781                                  FALSE : !server->standalone);
4782   }
4783
4784  out:
4785   silc_server_command_free(cmd);
4786 }
4787
4788 /* Server side of command USERS. Resolves clients and their USERS currently
4789    joined on the requested channel. The list of Client ID's and their modes
4790    on the channel is sent back. */
4791
4792 SILC_SERVER_CMD_FUNC(users)
4793 {
4794   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4795   SilcServer server = cmd->server;
4796   SilcIDListData idata = silc_packet_get_context(cmd->sock);
4797   SilcChannelEntry channel;
4798   SilcID id;
4799   SilcBuffer idp;
4800   unsigned char *channel_id;
4801   SilcUInt32 channel_id_len;
4802   SilcBuffer client_id_list;
4803   SilcBuffer client_mode_list;
4804   unsigned char lc[4];
4805   SilcUInt32 list_count = 0;
4806   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4807   char *channel_name, *channel_namec = NULL;
4808
4809   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4810
4811   /* Get Channel ID */
4812   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4813
4814   /* Get channel name */
4815   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4816
4817   if (!channel_id && !channel_name) {
4818     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4819                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4820     goto out;
4821   }
4822
4823   /* Check channel name */
4824   if (channel_name) {
4825     channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4826                                             SILC_STRING_UTF8, 256, NULL);
4827     if (!channel_namec) {
4828       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4829                                             SILC_STATUS_ERR_BAD_CHANNEL, 0);
4830       goto out;
4831     }
4832   }
4833
4834   /* Check Channel ID */
4835   if (channel_id) {
4836     if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4837       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4838                                            SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4839                                            2, channel_id, channel_id_len);
4840       goto out;
4841     }
4842   }
4843
4844   /* If we are server and we don't know about this channel we will send
4845      the command to our router. If we know about the channel then we also
4846      have the list of users already. */
4847   if (channel_id)
4848     channel = silc_idlist_find_channel_by_id(server->local_list,
4849                                              SILC_ID_GET_ID(id), NULL);
4850   else
4851     channel = silc_idlist_find_channel_by_name(server->local_list,
4852                                                channel_namec, NULL);
4853
4854   if (!channel || (!server->standalone && (channel->disabled ||
4855                     !channel->users_resolved))) {
4856     if (server->server_type != SILC_ROUTER && !server->standalone &&
4857         !cmd->pending) {
4858       SilcBuffer tmpbuf;
4859
4860       /* Statistics */
4861       cmd->server->stat.commands_sent++;
4862
4863       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4864       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4865
4866       /* Send USERS command */
4867       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4868                               SILC_PACKET_COMMAND, cmd->packet->flags,
4869                               tmpbuf->data, silc_buffer_len(tmpbuf));
4870
4871       /* Reprocess this packet after received reply */
4872       silc_server_command_pending(server, SILC_COMMAND_USERS,
4873                                   silc_command_get_ident(cmd->payload),
4874                                   silc_server_command_users,
4875                                   silc_server_command_dup(cmd));
4876       cmd->pending = TRUE;
4877       silc_command_set_ident(cmd->payload, ident);
4878       silc_buffer_free(tmpbuf);
4879       goto out;
4880     }
4881
4882     /* Check the global list as well. */
4883     if (channel_id)
4884       channel = silc_idlist_find_channel_by_id(server->global_list,
4885                                                SILC_ID_GET_ID(id), NULL);
4886     else
4887       channel = silc_idlist_find_channel_by_name(server->global_list,
4888                                                  channel_namec, NULL);
4889     if (!channel) {
4890       /* Channel really does not exist */
4891       if (channel_id)
4892         silc_server_command_send_status_data(
4893                                     cmd, SILC_COMMAND_USERS,
4894                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4895                                     2, channel_id, channel_id_len);
4896       else
4897         silc_server_command_send_status_data(
4898                                     cmd, SILC_COMMAND_USERS,
4899                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4900                                     2, channel_name, strlen(channel_name));
4901       goto out;
4902     }
4903   }
4904
4905   /* If the channel is private or secret do not send anything, unless the
4906      user requesting this command is on the channel or is server */
4907   if (idata->conn_type == SILC_CONN_CLIENT) {
4908     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4909         && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4910                                           NULL)) {
4911       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4912                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4913                                            2, channel->channel_name,
4914                                            strlen(channel->channel_name));
4915       goto out;
4916     }
4917   }
4918
4919   /* Get the users list */
4920   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4921                                         &client_mode_list, &list_count)) {
4922     list_count = 0;
4923     client_id_list = NULL;
4924     client_mode_list = NULL;
4925   }
4926
4927   /* List count */
4928   SILC_PUT32_MSB(list_count, lc);
4929
4930   /* Send reply */
4931   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4932   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
4933                                  SILC_STATUS_OK, 0, ident, 4,
4934                                  2, idp->data, silc_buffer_len(idp),
4935                                  3, lc, 4,
4936                                  4, client_id_list ?
4937                                  client_id_list->data : NULL,
4938                                  client_id_list ?
4939                                  silc_buffer_len(client_id_list) : 0,
4940                                  5, client_mode_list ?
4941                                  client_mode_list->data : NULL,
4942                                  client_mode_list ?
4943                                  silc_buffer_len(client_mode_list) : 0);
4944   silc_buffer_free(idp);
4945   if (client_id_list)
4946     silc_buffer_free(client_id_list);
4947   if (client_mode_list)
4948     silc_buffer_free(client_mode_list);
4949
4950  out:
4951   silc_free(channel_namec);
4952   silc_server_command_free(cmd);
4953 }
4954
4955 /* Server side of command GETKEY. This fetches the client's public key
4956    from the server where to the client is connected. */
4957
4958 SILC_SERVER_CMD_FUNC(getkey)
4959 {
4960   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4961   SilcServer server = cmd->server;
4962   SilcClientEntry client;
4963   SilcServerEntry server_entry;
4964   SilcClientID client_id;
4965   SilcServerID server_id;
4966   SilcIDPayload idp = NULL;
4967   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4968   unsigned char *tmp;
4969   SilcUInt32 tmp_len;
4970   SilcBuffer pk = NULL;
4971   SilcIdType id_type;
4972   SilcPublicKey public_key;
4973
4974   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4975   if (!tmp) {
4976     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4977                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4978                                           0);
4979     goto out;
4980   }
4981   idp = silc_id_payload_parse(tmp, tmp_len);
4982   if (!idp) {
4983     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4984                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4985                                           0);
4986     goto out;
4987   }
4988
4989   id_type = silc_id_payload_get_type(idp);
4990   if (id_type == SILC_ID_CLIENT) {
4991     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
4992
4993     /* If the client is not found from local list there is no chance it
4994        would be locally connected client so send the command further. */
4995     client = silc_idlist_find_client_by_id(server->local_list,
4996                                            &client_id, TRUE, NULL);
4997     if (!client)
4998       client = silc_idlist_find_client_by_id(server->global_list,
4999                                              &client_id, TRUE, NULL);
5000
5001     if ((!client && !cmd->pending && !server->standalone) ||
5002         (client && !client->connection && !cmd->pending &&
5003          !(client->mode & SILC_UMODE_DETACHED)) ||
5004         (client && !client->data.public_key && !cmd->pending)) {
5005       SilcBuffer tmpbuf;
5006       SilcUInt16 old_ident;
5007       SilcPacketStream dest_sock;
5008
5009       dest_sock = silc_server_get_client_route(server, NULL, 0,
5010                                                &client_id, NULL, NULL);
5011       if (!dest_sock)
5012         goto out;
5013
5014       /* Statistics */
5015       cmd->server->stat.commands_sent++;
5016
5017       old_ident = silc_command_get_ident(cmd->payload);
5018       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5019       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5020
5021       silc_server_packet_send(server, dest_sock,
5022                               SILC_PACKET_COMMAND, cmd->packet->flags,
5023                               tmpbuf->data, silc_buffer_len(tmpbuf));
5024
5025       /* Reprocess this packet after received reply from router */
5026       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5027                                   silc_command_get_ident(cmd->payload),
5028                                   silc_server_command_getkey,
5029                                   silc_server_command_dup(cmd));
5030       cmd->pending = TRUE;
5031       silc_command_set_ident(cmd->payload, old_ident);
5032       silc_buffer_free(tmpbuf);
5033       goto out;
5034     }
5035
5036     if (!client) {
5037       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5038                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5039                                            0, 2, tmp, tmp_len);
5040       goto out;
5041     }
5042
5043     /* The client is locally connected, just get the public key and
5044        send it back. If they key does not exist then do not send it,
5045        send just OK reply */
5046     public_key = client->data.public_key;
5047     if (public_key)
5048       pk = silc_public_key_payload_encode(public_key);
5049   } else if (id_type == SILC_ID_SERVER) {
5050     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5051
5052     /* If the server is not found from local list there is no chance it
5053        would be locally connected server so send the command further. */
5054     server_entry = silc_idlist_find_server_by_id(server->local_list,
5055                                                  &server_id, TRUE, NULL);
5056     if (!server_entry)
5057       server_entry = silc_idlist_find_server_by_id(server->global_list,
5058                                                    &server_id, TRUE, NULL);
5059
5060     if (server_entry != server->id_entry &&
5061         ((!server_entry && !cmd->pending && !server->standalone) ||
5062          (server_entry && !server_entry->connection && !cmd->pending &&
5063           !server->standalone) ||
5064          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5065           !server->standalone))) {
5066       SilcBuffer tmpbuf;
5067       SilcUInt16 old_ident;
5068
5069       /* Statistics */
5070       cmd->server->stat.commands_sent++;
5071
5072       old_ident = silc_command_get_ident(cmd->payload);
5073       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5074       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5075
5076       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5077                               SILC_PACKET_COMMAND, cmd->packet->flags,
5078                               tmpbuf->data, silc_buffer_len(tmpbuf));
5079
5080       /* Reprocess this packet after received reply from router */
5081       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5082                                   silc_command_get_ident(cmd->payload),
5083                                   silc_server_command_getkey,
5084                                   silc_server_command_dup(cmd));
5085       cmd->pending = TRUE;
5086       silc_command_set_ident(cmd->payload, old_ident);
5087       silc_buffer_free(tmpbuf);
5088       goto out;
5089     }
5090
5091     if (!server_entry) {
5092       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5093                                            SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5094                                            0, 2, tmp, tmp_len);
5095       goto out;
5096     }
5097
5098     /* If they key does not exist then do not send it, send just OK reply */
5099     public_key = (!server_entry->data.public_key ?
5100                   (server_entry == server->id_entry ? server->public_key :
5101                    NULL) : server_entry->data.public_key);
5102     if (public_key)
5103       pk = silc_public_key_payload_encode(public_key);
5104   } else {
5105     goto out;
5106   }
5107
5108   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5109   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5110                                  SILC_STATUS_OK, 0, ident, 2,
5111                                  2, tmp, tmp_len,
5112                                  3, pk ? pk->data : NULL,
5113                                  pk ? silc_buffer_len(pk) : 0);
5114
5115  out:
5116   if (idp)
5117     silc_id_payload_free(idp);
5118   silc_buffer_free(pk);
5119   silc_server_command_free(cmd);
5120 }
5121
5122 /* Server side of command SERVICE. */
5123 /* XXX currently this just sends empty reply back */
5124
5125 SILC_SERVER_CMD_FUNC(service)
5126 {
5127   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5128   SilcServer server = cmd->server;
5129   SilcUInt32 tmp_len, auth_len;
5130   unsigned char *service_name, *auth;
5131   SilcBool send_list = FALSE;
5132   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5133
5134   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5135
5136   /* Get requested service */
5137   service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5138   if (service_name && tmp_len) {
5139     /* Verify service name */
5140     if (!silc_identifier_verify(service_name, tmp_len,
5141                                 SILC_STRING_UTF8, 256)) {
5142       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5143                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5144                                             0);
5145       goto out;
5146     }
5147   }
5148
5149   /* Get authentication payload if present */
5150   auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5151   if (auth) {
5152     /* XXX */
5153   }
5154
5155
5156   send_list = TRUE;
5157
5158   /* Send our service list back */
5159   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5160                                  SILC_STATUS_OK, 0, ident, 0);
5161
5162  out:
5163   silc_server_command_free(cmd);
5164 }
5165
5166
5167 /* Private range commands, specific to this implementation */
5168
5169 /* Server side command of CONNECT. Connects us to the specified remote
5170    server or router. */
5171
5172 SILC_SERVER_CMD_FUNC(connect)
5173 {
5174   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5175   SilcServer server = cmd->server;
5176   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5177   unsigned char *tmp, *host;
5178   SilcUInt32 tmp_len;
5179   SilcUInt32 port = SILC_PORT;
5180
5181   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5182     goto out;
5183
5184   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5185
5186   /* Check whether client has the permissions. */
5187   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5188       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5189     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5190                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5191     goto out;
5192   }
5193
5194   if (server->server_type == SILC_ROUTER && !server->backup_router &&
5195       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5196     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5197                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5198     goto out;
5199   }
5200
5201   /* Get the remote server */
5202   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5203   if (!host) {
5204     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5205                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5206                                           0);
5207     goto out;
5208   }
5209
5210   /* Get port */
5211   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5212   if (tmp)
5213     SILC_GET32_MSB(port, tmp);
5214
5215   /* Create the connection. It is done with timeout and is async. */
5216   silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5217
5218   /* Send reply to the sender */
5219   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5220                                         SILC_STATUS_OK, 0);
5221
5222  out:
5223   silc_server_command_free(cmd);
5224 }
5225
5226 /* Server side command of CLOSE. Closes connection to a specified server. */
5227
5228 SILC_SERVER_CMD_FUNC(close)
5229 {
5230   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5231   SilcServer server = cmd->server;
5232   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5233   SilcServerEntry server_entry;
5234   SilcPacketStream sock;
5235   unsigned char *tmp;
5236   SilcUInt32 tmp_len;
5237   unsigned char *name;
5238   SilcUInt32 port = SILC_PORT;
5239
5240   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5241     goto out;
5242
5243   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5244
5245   /* Check whether client has the permissions. */
5246   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5247       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5248     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5249                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5250                                           0);
5251     goto out;
5252   }
5253
5254   /* Get the remote server */
5255   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5256   if (!name) {
5257     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5258                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5259                                           0);
5260     goto out;
5261   }
5262
5263   /* Get port */
5264   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5265   if (tmp)
5266     SILC_GET32_MSB(port, tmp);
5267
5268   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5269                                                  name, port, TRUE, NULL);
5270   if (!server_entry)
5271     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5272                                                    name, port, TRUE, NULL);
5273   if (!server_entry) {
5274     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5275                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5276     goto out;
5277   }
5278
5279   if (server_entry == server->id_entry) {
5280     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5281                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5282     goto out;
5283   }
5284
5285   /* Send reply to the sender */
5286   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5287                                         SILC_STATUS_OK, 0);
5288
5289   /* Close the connection to the server */
5290   sock = server_entry->connection;
5291
5292   if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5293     server->backup_closed = TRUE;
5294     silc_server_backup_del(server, server_entry);
5295   }
5296
5297   server->backup_noswitch = TRUE;
5298   if (server->router == server_entry) {
5299     server->id_entry->router = NULL;
5300     server->router = NULL;
5301     server->standalone = TRUE;
5302   }
5303   silc_server_disconnect_remote(server, sock,
5304                                 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5305                                 "Closed by administrator");
5306   silc_server_free_sock_user_data(server, sock, NULL);
5307   server->backup_noswitch = FALSE;
5308
5309  out:
5310   silc_server_command_free(cmd);
5311 }
5312
5313 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5314    active connections. */
5315
5316 SILC_SERVER_CMD_FUNC(shutdown)
5317 {
5318   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5319   SilcServer server = cmd->server;
5320   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5321
5322   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5323     goto out;
5324
5325   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5326
5327   /* Check whether client has the permission. */
5328   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5329       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5330     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5331                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5332                                           0);
5333     goto out;
5334   }
5335
5336   /* Send reply to the sender */
5337   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5338                                         SILC_STATUS_OK, 0);
5339
5340   /* Then, gracefully, or not, bring the server down. */
5341   silc_server_stop(server);
5342   exit(0);
5343
5344  out:
5345   silc_server_command_free(cmd);
5346 }