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