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