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