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