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