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