Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 static int silc_server_is_registered(SilcServer server,
25                                      SilcPacketStream sock,
26                                      SilcServerCommandContext cmd,
27                                      SilcCommand command);
28 static void
29 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
30                                       SilcCommand command,
31                                       SilcStatus status,
32                                       SilcStatus error);
33 static void
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcStatus status,
37                                      SilcStatus error,
38                                      SilcUInt32 arg_type,
39                                      const unsigned char *arg,
40                                      SilcUInt32 arg_len);
41 static bool
42 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
43                                         SilcServerCommandReplyContext cmdr,
44                                         SilcCommand command);
45 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46
47 /* Server command list. */
48 SilcServerCommand silc_command_list[] =
49 {
50   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
54   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
55   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
56   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
60   SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
71   SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
72   SILC_SERVER_CMD(silcoper, SILCOPER,
73                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
74   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
75   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
76   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
77   SILC_SERVER_CMD(service, SERVICE, SILC_CF_LAG_STRICT | SILC_CF_REG),
78
79   SILC_SERVER_CMD(connect, PRIV_CONNECT,
80                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81   SILC_SERVER_CMD(close, PRIV_CLOSE,
82                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
84                   SILC_CF_OPER),
85
86   { NULL, 0 },
87 };
88
89 /* Performs several checks to the command. It first checks whether this
90    command was called as pending command callback. If it was then it checks
91    whether error occurred in the command reply where the pending command
92    callback was called.
93
94    It also checks that the requested command includes correct amount
95    of arguments. */
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                \
97 do {                                                                         \
98   SilcUInt32 _argc;                                                          \
99                                                                              \
100   if (silc_server_command_pending_error_check(cmd, context2, command)) {     \
101     SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102     silc_server_command_free(cmd);                                           \
103     return;                                                                  \
104   }                                                                          \
105                                                                              \
106   _argc = silc_argument_get_arg_num(cmd->args);                              \
107   if (_argc < min) {                                                         \
108     SILC_LOG_DEBUG(("Not enough parameters in command"));                    \
109     silc_server_command_send_status_reply(cmd, command,                      \
110                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
111                                           0);                                \
112     silc_server_command_free(cmd);                                           \
113     return;                                                                  \
114   }                                                                          \
115   if (_argc > max) {                                                         \
116     SILC_LOG_DEBUG(("Too many parameters in command"));                      \
117     silc_server_command_send_status_reply(cmd, command,                      \
118                                           SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
119                                           0);                                \
120     silc_server_command_free(cmd);                                           \
121     return;                                                                  \
122   }                                                                          \
123 } while(0)
124
125 /* Returns TRUE if the connection is registered. Unregistered connections
126    usually cannot send commands hence the check. */
127
128 static int silc_server_is_registered(SilcServer server,
129                                      SilcPacketStream sock,
130                                      SilcServerCommandContext cmd,
131                                      SilcCommand command)
132 {
133   SilcIDListData idata = silc_packet_get_context(sock);
134
135   if (!idata)
136     return FALSE;
137
138   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
139     return TRUE;
140
141   silc_server_command_send_status_reply(cmd, command,
142                                         SILC_STATUS_ERR_NOT_REGISTERED, 0);
143   return FALSE;
144 }
145
146 /* Internal context to hold data when executed command with timeout. */
147 typedef struct {
148   SilcServerCommandContext ctx;
149   SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
151
152 /* Timeout callback to process commands with timeout for client. Client's
153    commands are always executed with timeout. */
154
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 {
157   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158   SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
159
160   if (!client) {
161     SILC_LOG_DEBUG(("Client entry is invalid"));
162     silc_server_command_free(timeout->ctx);
163     silc_free(timeout);
164     return;
165   }
166
167   /* Update access time */
168   client->last_command = time(NULL);
169
170   if (!(timeout->cmd->flags & SILC_CF_REG)) {
171     SILC_LOG_DEBUG(("Calling %s command",
172                     silc_get_command_name(timeout->cmd->cmd)));
173     timeout->cmd->cb(timeout->ctx, NULL);
174   } else if (silc_server_is_registered(timeout->ctx->server,
175                                        timeout->ctx->sock,
176                                        timeout->ctx,
177                                        timeout->cmd->cmd)) {
178     SILC_LOG_DEBUG(("Calling %s command",
179                     silc_get_command_name(timeout->cmd->cmd)));
180     timeout->cmd->cb(timeout->ctx, NULL);
181   } else {
182     SILC_LOG_DEBUG(("Client is not registered"));
183     silc_server_command_free(timeout->ctx);
184   }
185
186   silc_free(timeout);
187 }
188
189 /* Processes received command packet. */
190
191 void silc_server_command_process(SilcServer server,
192                                  SilcPacketStream sock,
193                                  SilcPacket packet)
194 {
195   SilcIDListData idata = silc_packet_get_context(sock);
196   SilcServerCommandContext ctx;
197   SilcServerCommand *cmd;
198   SilcCommand command;
199
200   if (!idata)
201     return;
202
203   /* Allocate command context. This must be free'd by the
204      command routine receiving it. */
205   ctx = silc_server_command_alloc();
206   ctx->server = server;
207   ctx->sock = sock;
208   ctx->packet = packet; /* Save original packet */
209   silc_packet_stream_ref(sock);
210
211   /* Parse the command payload in the packet */
212   ctx->payload = silc_command_payload_parse(packet->buffer.data,
213                                             silc_buffer_len(&packet->buffer));
214   if (!ctx->payload) {
215     SILC_LOG_ERROR(("Bad command payload"));
216     silc_packet_free(packet);
217     silc_packet_stream_unref(ctx->sock);
218     silc_free(ctx);
219     return;
220   }
221   ctx->args = silc_command_get_args(ctx->payload);
222
223   /* Get the command */
224   command = silc_command_get(ctx->payload);
225   for (cmd = silc_command_list; cmd->cb; cmd++)
226     if (cmd->cmd == command)
227       break;
228
229   if (!cmd || !cmd->cb) {
230     SILC_LOG_DEBUG(("Unknown command %d", command));
231     silc_server_command_send_status_reply(ctx, command,
232                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
233     silc_packet_free(packet);
234     silc_packet_stream_unref(ctx->sock);
235     silc_free(ctx);
236     return;
237   }
238
239   /* Execute client's commands always with timeout.  Normally they are
240      executed with zero (0) timeout but if client is sending command more
241      frequently than once in 2 seconds, then the timeout may be 0 to 2
242      seconds. */
243   if (idata->conn_type == SILC_CONN_CLIENT) {
244     SilcClientEntry client = silc_packet_get_context(sock);
245     SilcServerCommandTimeout timeout;
246     int fast;
247
248     timeout = silc_calloc(1, sizeof(*timeout));
249     timeout->ctx = ctx;
250     timeout->cmd = cmd;
251
252     if (client->last_command && (time(NULL) - client->last_command) < 2) {
253       client->fast_command++;
254       fast = FALSE;
255     } else {
256       if (client->fast_command - 2 <= 0)
257         client->fast_command = 0;
258       else
259         client->fast_command -= 2;
260       fast = TRUE;
261     }
262
263     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
264                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
265       silc_schedule_task_add_timeout(
266                             server->schedule,
267                             silc_server_command_process_timeout, timeout,
268                             (client->fast_command < 3 ? 0 :
269                              2 - (time(NULL) - client->last_command)),
270                             (client->fast_command < 3 ? 200000 : 0));
271     else
272       silc_schedule_task_add_timeout(server->schedule,
273                                      silc_server_command_process_timeout,
274                                      timeout, 0, 0);
275     return;
276   }
277
278   /* Execute for server */
279
280   if (!(cmd->flags & SILC_CF_REG)) {
281     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
282     cmd->cb(ctx, NULL);
283   } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
284     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
285     cmd->cb(ctx, NULL);
286   } else {
287     SILC_LOG_DEBUG(("Server is not registered"));
288     silc_server_command_free(ctx);
289   }
290 }
291
292 /* Allocate Command Context */
293
294 SilcServerCommandContext silc_server_command_alloc()
295 {
296   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
297   ctx->users++;
298   return ctx;
299 }
300
301 /* Free's the command context allocated before executing the command */
302
303 void silc_server_command_free(SilcServerCommandContext ctx)
304 {
305   ctx->users--;
306   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
307                   ctx->users));
308   if (ctx->users < 1) {
309     if (ctx->payload)
310       silc_command_payload_free(ctx->payload);
311     if (ctx->packet)
312       silc_packet_free(ctx->packet);
313     if (ctx->sock)
314       silc_packet_stream_unref(ctx->sock);
315     silc_free(ctx);
316   }
317 }
318
319 /* Duplicate Command Context by adding reference counter. The context won't
320    be free'd untill it hits zero. */
321
322 SilcServerCommandContext
323 silc_server_command_dup(SilcServerCommandContext ctx)
324 {
325   ctx->users++;
326   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
327                   ctx->users));
328   return ctx;
329 }
330
331 /* Timeout for pending command.  If reply to pending command never arrives
332    this is called to free resources. */
333
334 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
335 {
336   SilcServer server = app_context;
337   SilcServerCommandPending *reply = context;
338   SilcServerCommandReplyContext cmdr;
339   SilcBuffer tmpreply;
340   int i;
341
342   SILC_LOG_DEBUG(("Timeout pending command"));
343
344   /* Allocate temporary and bogus command reply context */
345   cmdr = silc_calloc(1, sizeof(*cmdr));
346   cmdr->server = server;
347   cmdr->ident = reply->ident;
348
349   /* Check for pending commands and mark to be exeucted */
350   cmdr->callbacks =
351     silc_server_command_pending_check(server, reply->reply_cmd,
352                                       reply->ident, &cmdr->callbacks_count);
353
354   /* Create bogus command reply with an error inside */
355   tmpreply =
356     silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
357                                          SILC_COMMAND_RESERVED,
358                                          SILC_STATUS_ERR_TIMEDOUT, 0,
359                                          reply->ident, 0);
360   cmdr->payload = silc_command_payload_parse(tmpreply->data,
361                                              silc_buffer_len(tmpreply));
362   silc_buffer_free(tmpreply);
363
364   /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
365   for (i = 0; i < cmdr->callbacks_count; i++)
366     if (cmdr->callbacks[i].callback)
367       (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
368
369   silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
370   silc_server_command_reply_free(cmdr);
371 }
372
373 /* Add new pending command to be executed when reply to a command has been
374    received. The `reply_cmd' is the command that will call the `callback'
375    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
376    to match any command with the `ident'.  If `ident' is non-zero
377    the `callback' will be executed when received reply with command
378    identifier `ident'. If there already exists pending command for the
379    specified command, ident, callback and context this function has no
380    effect. */
381
382 SilcBool silc_server_command_pending(SilcServer server,
383                                  SilcCommand reply_cmd,
384                                  SilcUInt16 ident,
385                                  SilcCommandCb callback,
386                                  void *context)
387 {
388   return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
389                                            context, 0);
390 }
391
392 /* Same as silc_server_command_pending with specific timeout for pending
393    commands.  If the `timeout' is zero default timeout is used. */
394
395 SilcBool silc_server_command_pending_timed(SilcServer server,
396                                        SilcCommand reply_cmd,
397                                        SilcUInt16 ident,
398                                        SilcCommandCb callback,
399                                        void *context,
400                                        SilcUInt16 timeout)
401 {
402   SilcServerCommandPending *reply;
403
404   /* Check whether identical pending already exists for same command,
405      ident, callback and callback context. If it does then it would be
406      error to register it again. */
407   silc_dlist_start(server->pending_commands);
408   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
409     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
410         reply->callback == callback && reply->context == context)
411       return FALSE;
412   }
413
414   reply = silc_calloc(1, sizeof(*reply));
415   reply->reply_cmd = reply_cmd;
416   reply->ident = ident;
417   reply->context = context;
418   reply->callback = callback;
419   reply->timeout =
420     silc_schedule_task_add_timeout(server->schedule,
421                                    silc_server_command_pending_timeout, reply,
422                                    timeout ? timeout : 12, 0);
423   silc_dlist_add(server->pending_commands, reply);
424
425   return TRUE;
426 }
427
428 /* Deletes pending command by reply command type. */
429
430 void silc_server_command_pending_del(SilcServer server,
431                                      SilcCommand reply_cmd,
432                                      SilcUInt16 ident)
433 {
434   SilcServerCommandPending *r;
435
436   silc_dlist_start(server->pending_commands);
437   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
438     if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
439                                        r->reply_check))
440         && r->ident == ident) {
441       silc_dlist_del(server->pending_commands, r);
442       if (r->timeout)
443         silc_schedule_task_del(server->schedule, r->timeout);
444       silc_free(r);
445     }
446   }
447 }
448
449 /* Checks for pending commands and marks callbacks to be called from
450    the command reply function. Returns TRUE if there were pending command. */
451
452 SilcServerCommandPendingCallbacks
453 silc_server_command_pending_check(SilcServer server,
454                                   SilcCommand command,
455                                   SilcUInt16 ident,
456                                   SilcUInt32 *callbacks_count)
457 {
458   SilcServerCommandPending *r;
459   SilcServerCommandPendingCallbacks callbacks = NULL;
460   int i = 0;
461
462   silc_dlist_start(server->pending_commands);
463   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
464     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
465         && r->ident == ident) {
466       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
467       callbacks[i].context = r->context;
468       callbacks[i].callback = r->callback;
469       r->reply_check = TRUE;
470       i++;
471     }
472   }
473
474   *callbacks_count = i;
475   return callbacks;
476 }
477
478 /* Sends simple status message as command reply packet */
479
480 static void
481 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
482                                       SilcCommand command,
483                                       SilcStatus status,
484                                       SilcStatus error)
485 {
486   SilcBuffer buffer;
487
488   /* Statistics */
489   cmd->server->stat.commands_sent++;
490
491   SILC_LOG_DEBUG(("Sending command status %d", status));
492
493   buffer =
494     silc_command_reply_payload_encode_va(command, status, error,
495                                          silc_command_get_ident(cmd->payload),
496                                          0);
497   silc_server_packet_send(cmd->server, cmd->sock,
498                           SILC_PACKET_COMMAND_REPLY, 0,
499                           buffer->data, silc_buffer_len(buffer));
500   silc_buffer_free(buffer);
501 }
502
503 /* Sends command status reply with one extra argument. The argument
504    type must be sent as argument. */
505
506 static void
507 silc_server_command_send_status_data(SilcServerCommandContext cmd,
508                                      SilcCommand command,
509                                      SilcStatus status,
510                                      SilcStatus error,
511                                      SilcUInt32 arg_type,
512                                      const unsigned char *arg,
513                                      SilcUInt32 arg_len)
514 {
515   SilcBuffer buffer;
516
517   /* Statistics */
518   cmd->server->stat.commands_sent++;
519
520   SILC_LOG_DEBUG(("Sending command status %d", status));
521
522   buffer =
523     silc_command_reply_payload_encode_va(command, status, 0,
524                                          silc_command_get_ident(cmd->payload),
525                                          1, arg_type, arg, arg_len);
526   silc_server_packet_send(cmd->server, cmd->sock,
527                           SILC_PACKET_COMMAND_REPLY, 0,
528                           buffer->data, silc_buffer_len(buffer));
529   silc_buffer_free(buffer);
530 }
531
532 static void
533 silc_server_command_send_status_data2(SilcServerCommandContext cmd,
534                                       SilcCommand command,
535                                       SilcStatus status,
536                                       SilcStatus error,
537                                       SilcUInt32 arg_type1,
538                                       const unsigned char *arg1,
539                                       SilcUInt32 arg_len1,
540                                       SilcUInt32 arg_type2,
541                                       const unsigned char *arg2,
542                                       SilcUInt32 arg_len2)
543 {
544   SilcBuffer buffer;
545
546   /* Statistics */
547   cmd->server->stat.commands_sent++;
548
549   SILC_LOG_DEBUG(("Sending command status %d", status));
550
551   buffer =
552     silc_command_reply_payload_encode_va(command, status, 0,
553                                          silc_command_get_ident(cmd->payload),
554                                          2, arg_type1, arg1, arg_len1,
555                                          arg_type2, arg2, arg_len2);
556   silc_server_packet_send(cmd->server, cmd->sock,
557                           SILC_PACKET_COMMAND_REPLY, 0,
558                           buffer->data, silc_buffer_len(buffer));
559   silc_buffer_free(buffer);
560 }
561
562 /* This function can be called to check whether in the command reply
563    an error occurred. This function has no effect if this is called
564    when the command function was not called as pending command callback.
565    This returns TRUE if error had occurred. */
566
567 static bool
568 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
569                                         SilcServerCommandReplyContext cmdr,
570                                         SilcCommand command)
571 {
572   if (!cmd->pending || !cmdr)
573     return FALSE;
574
575   if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
576     SilcBuffer buffer;
577
578     /* Statistics */
579     cmd->server->stat.commands_sent++;
580
581     /* Send the same command reply payload */
582     silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
583     silc_command_set_ident(cmdr->payload,
584                            silc_command_get_ident(cmd->payload));
585     buffer = silc_command_payload_encode_payload(cmdr->payload);
586     silc_server_packet_send(cmd->server, cmd->sock,
587                             SILC_PACKET_COMMAND_REPLY, 0,
588                             buffer->data, silc_buffer_len(buffer));
589     silc_buffer_free(buffer);
590     return TRUE;
591   }
592
593   return FALSE;
594 }
595
596 /* Server side of command WHOIS. */
597
598 SILC_SERVER_CMD_FUNC(whois)
599 {
600   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
601   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
602   silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
603   silc_server_command_free(cmd);
604 }
605
606 /* Server side of command WHOWAS. */
607
608 SILC_SERVER_CMD_FUNC(whowas)
609 {
610   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
611   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
612   silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
613   silc_server_command_free(cmd);
614 }
615
616 /* Server side of command IDENTIFY. */
617
618 SILC_SERVER_CMD_FUNC(identify)
619 {
620   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
621   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
622   silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
623   silc_server_command_free(cmd);
624 }
625
626 /* Server side of command NICK. Sets nickname for user. Setting
627    nickname causes generation of a new client ID for the client. The
628    new client ID is sent to the client after changing the nickname. */
629
630 SILC_SERVER_CMD_FUNC(nick)
631 {
632   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
633   SilcClientEntry client = silc_packet_get_context(cmd->sock);
634   SilcServer server = cmd->server;
635   SilcBuffer nidp, oidp = NULL;
636   SilcClientID *new_id;
637   SilcUInt32 nick_len;
638   unsigned char *nick, *nickc = NULL;
639   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
640
641   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
642     goto out;
643
644   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
645
646   /* Get nickname */
647   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
648   if (!nick) {
649     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
650                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
651     goto out;
652   }
653
654   /* Truncate over long nicks */
655   if (nick_len > 128) {
656     nick_len = 128;
657     nick[nick_len - 1] = '\0';
658   }
659
660   /* Check for valid nickname string.  This is cached, original is saved
661      in the client context. */
662   nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL);
663   if (!nickc) {
664     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
665                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
666     goto out;
667   }
668
669   /* Check for same nickname */
670   if (strlen(client->nickname) == nick_len &&
671       !memcmp(client->nickname, nick, nick_len)) {
672     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
673     silc_free(nickc);
674     goto send_reply;
675   }
676
677   /* Create new Client ID */
678   if (!silc_id_create_client_id(cmd->server, cmd->server->id,
679                                 cmd->server->rng,
680                                 cmd->server->md5hash,
681                                 nickc, strlen(nickc), &new_id)) {
682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
684     silc_free(nickc);
685     goto out;
686   }
687
688   /* Send notify about nickname change to our router. We send the new
689      ID and ask to replace it with the old one. If we are router the
690      packet is broadcasted. Send NICK_CHANGE notify. */
691   silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
692                                       SILC_BROADCAST(server), client->id,
693                                       new_id, nick);
694
695   /* Check if anyone is watching the old nickname */
696   if (server->server_type == SILC_ROUTER)
697     silc_server_check_watcher_list(server, client, nick,
698                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
699
700   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
701
702   /* Update client entry */
703   silc_idcache_update_by_context(server->local_list->clients, client,
704                                  new_id, nickc, TRUE);
705   silc_free(new_id);
706   silc_free(client->nickname);
707   client->nickname = strdup(nick);
708
709   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
710
711   /* Send NICK_CHANGE notify to the client's channels */
712   silc_server_send_notify_on_channels(server, NULL, client,
713                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
714                                       oidp->data, silc_buffer_len(oidp),
715                                       nidp->data, silc_buffer_len(nidp),
716                                       client->nickname,
717                                       strlen(client->nickname));
718
719   /* Check if anyone is watching the new nickname */
720   if (server->server_type == SILC_ROUTER)
721     silc_server_check_watcher_list(server, client, NULL,
722                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
723
724  send_reply:
725   /* Send the new Client ID as reply command back to client */
726   silc_server_send_command_reply(cmd->server, cmd->sock,
727                                  SILC_COMMAND_NICK,
728                                  SILC_STATUS_OK, 0, ident, 2,
729                                  2, nidp->data, silc_buffer_len(nidp),
730                                  3, nick, nick_len);
731   silc_buffer_free(nidp);
732   if (oidp)
733     silc_buffer_free(oidp);
734
735  out:
736   silc_server_command_free(cmd);
737 }
738
739 /* Sends the LIST command reply */
740
741 static void
742 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
743                                     SilcChannelEntry *lch,
744                                     SilcUInt32 lch_count,
745                                     SilcChannelEntry *gch,
746                                     SilcUInt32 gch_count)
747 {
748   int i, k;
749   SilcBuffer idp;
750   SilcChannelEntry entry;
751   SilcStatus status;
752   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
753   char *topic;
754   unsigned char usercount[4];
755   SilcUInt32 users;
756   int valid_lcount = 0, valid_rcount = 0;
757
758   for (i = 0; i < lch_count; i++) {
759     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
760       lch[i] = NULL;
761     else
762       valid_lcount++;
763   }
764   for (i = 0; i < gch_count; i++) {
765     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
766       gch[i] = NULL;
767     else
768       valid_rcount++;
769   }
770
771   if (!lch_count && !gch_count) {
772     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
773                                           SILC_STATUS_OK, 0);
774     return;
775   }
776
777   status = SILC_STATUS_OK;
778   if ((lch_count + gch_count) > 1)
779     status = SILC_STATUS_LIST_START;
780
781   /* Local list */
782   for (i = 0, k = 0; i < lch_count; i++) {
783     entry = lch[i];
784     if (!entry)
785       continue;
786
787     if (k >= 1)
788       status = SILC_STATUS_LIST_ITEM;
789     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
790       status = SILC_STATUS_LIST_END;
791
792     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
793
794     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
795       topic = "*private*";
796       memset(usercount, 0, sizeof(usercount));
797     } else {
798       topic = entry->topic;
799       users = silc_hash_table_count(entry->user_list);
800       SILC_PUT32_MSB(users, usercount);
801     }
802
803     /* Send the reply */
804     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
805                                    status, 0, ident, 4,
806                                    2, idp->data, silc_buffer_len(idp),
807                                    3, entry->channel_name,
808                                    strlen(entry->channel_name),
809                                    4, topic, topic ? strlen(topic) : 0,
810                                    5, usercount, 4);
811     silc_buffer_free(idp);
812     k++;
813   }
814
815   /* Global list */
816   for (i = 0, k = 0; i < gch_count; i++) {
817     entry = gch[i];
818     if (!entry)
819       continue;
820
821     if (k >= 1)
822       status = SILC_STATUS_LIST_ITEM;
823     if (valid_rcount > 1 && k == valid_rcount - 1)
824       status = SILC_STATUS_LIST_END;
825
826     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
827
828     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
829       topic = "*private*";
830       memset(usercount, 0, sizeof(usercount));
831     } else {
832       topic = entry->topic;
833       users = entry->user_count;
834       SILC_PUT32_MSB(users, usercount);
835     }
836
837     /* Send the reply */
838     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
839                                    status, 0, ident, 4,
840                                    2, idp->data, silc_buffer_len(idp),
841                                    3, entry->channel_name,
842                                    strlen(entry->channel_name),
843                                    4, topic, topic ? strlen(topic) : 0,
844                                    5, usercount, 4);
845     silc_buffer_free(idp);
846     k++;
847   }
848 }
849
850 /* Server side of LIST command. This lists the channel of the requested
851    server. Secret channels are not listed. */
852
853 SILC_SERVER_CMD_FUNC(list)
854 {
855   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
856   SilcServer server = cmd->server;
857   SilcID id;
858   SilcChannelID *channel_id = NULL;
859   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
860   SilcUInt32 lch_count = 0, gch_count = 0;
861
862   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
863
864   /* If we are normal server, send the command to router, since we
865      want to know all channels in the network. */
866   if (!cmd->pending && server->server_type != SILC_ROUTER &&
867       !server->standalone) {
868     SilcBuffer tmpbuf;
869     SilcUInt16 old_ident;
870
871     /* Statistics */
872     cmd->server->stat.commands_sent++;
873
874     old_ident = silc_command_get_ident(cmd->payload);
875     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
876     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
877     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
878                             SILC_PACKET_COMMAND, cmd->packet->flags,
879                             tmpbuf->data, silc_buffer_len(tmpbuf));
880
881     /* Reprocess this packet after received reply from router */
882     silc_server_command_pending(server, SILC_COMMAND_LIST,
883                                 silc_command_get_ident(cmd->payload),
884                                 silc_server_command_list,
885                                 silc_server_command_dup(cmd));
886     cmd->pending = TRUE;
887     silc_command_set_ident(cmd->payload, old_ident);
888     silc_buffer_free(tmpbuf);
889     goto out;
890   }
891
892   /* Get Channel ID */
893   if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
894     channel_id = SILC_ID_GET_ID(id);
895
896   /* Get the channels from local list */
897   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
898                                        &lch_count);
899
900   /* Get the channels from global list */
901   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
902                                        &gch_count);
903
904   /* Send the reply */
905   silc_server_command_list_send_reply(cmd, lchannels, lch_count,
906                                       gchannels, gch_count);
907
908   silc_free(lchannels);
909   silc_free(gchannels);
910
911  out:
912   silc_server_command_free(cmd);
913 }
914
915 /* Server side of TOPIC command. Sets topic for channel and/or returns
916    current topic to client. */
917
918 SILC_SERVER_CMD_FUNC(topic)
919 {
920   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
921   SilcServer server = cmd->server;
922   SilcClientEntry client = silc_packet_get_context(cmd->sock);
923   SilcID id;
924   SilcChannelEntry channel;
925   SilcChannelClientEntry chl;
926   SilcBuffer idp;
927   unsigned char *tmp;
928   SilcUInt32 argc, tmp_len;
929   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
930
931   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
932     goto out;
933
934   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
935
936   argc = silc_argument_get_arg_num(cmd->args);
937
938   /* Get Channel ID */
939   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
940     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
941                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
942     goto out;
943   }
944
945   /* Check whether the channel exists */
946   channel = silc_idlist_find_channel_by_id(server->local_list,
947                                            SILC_ID_GET_ID(id), NULL);
948   if (!channel) {
949     channel = silc_idlist_find_channel_by_id(server->global_list,
950                                              SILC_ID_GET_ID(id), NULL);
951     if (!channel) {
952       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
953       silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
954                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
955                                            0, 2, tmp, tmp_len);
956       goto out;
957     }
958   }
959
960   if (argc > 1) {
961     /* Get the topic */
962     tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
963     if (!tmp) {
964       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
965                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
966                                             0);
967       goto out;
968     }
969     if (tmp_len > 256) {
970       tmp_len = 256;
971       tmp[tmp_len - 1] = '\0';
972     }
973
974     if (!silc_utf8_valid(tmp, tmp_len)) {
975       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
976                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
977                                             0);
978       goto out;
979     }
980
981     /* See whether the client is on channel and has rights to change topic */
982     if (!silc_server_client_on_channel(client, channel, &chl)) {
983       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
984       silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
985                                            SILC_STATUS_ERR_NOT_ON_CHANNEL,
986                                            0, 2, tmp, tmp_len);
987       goto out;
988     }
989
990     if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
991         !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
992         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
993       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
994       silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
995                                            SILC_STATUS_ERR_NO_CHANNEL_PRIV,
996                                            0, 2, tmp, tmp_len);
997       goto out;
998     }
999
1000     if (!channel->topic || strcmp(channel->topic, tmp)) {
1001       /* Set the topic for channel */
1002       silc_free(channel->topic);
1003       channel->topic = strdup(tmp);
1004
1005       /* Send TOPIC_SET notify type to the network */
1006       silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1007                                         SILC_BROADCAST(server), channel,
1008                                         client->id, SILC_ID_CLIENT,
1009                                         channel->topic);
1010
1011       /* Send notify about topic change to all clients on the channel */
1012       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1013       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1014                                          SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1015                                          idp->data, silc_buffer_len(idp),
1016                                          channel->topic,
1017                                          strlen(channel->topic));
1018       silc_buffer_free(idp);
1019     }
1020   }
1021
1022   /* Send the topic to client as reply packet */
1023   idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1024   silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
1025                                  SILC_STATUS_OK, 0, ident, 2,
1026                                  2, idp->data, silc_buffer_len(idp),
1027                                  3, channel->topic,
1028                                  channel->topic ?
1029                                  strlen(channel->topic) : 0);
1030   silc_buffer_free(idp);
1031
1032  out:
1033   silc_server_command_free(cmd);
1034 }
1035
1036 /* Server side of INVITE command. Invites some client to join some channel.
1037    This command is also used to manage the invite list of the channel. */
1038
1039 SILC_SERVER_CMD_FUNC(invite)
1040 {
1041   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1042   SilcServer server = cmd->server;
1043   SilcPacketStream sock = cmd->sock, dest_sock;
1044   SilcChannelClientEntry chl;
1045   SilcClientEntry sender, dest;
1046   SilcChannelEntry channel;
1047   SilcID id, id2;
1048   SilcIDListData idata;
1049   SilcArgumentPayload args;
1050   SilcHashTableList htl;
1051   SilcBuffer list, tmp2;
1052   SilcBufferStruct alist;
1053   unsigned char *tmp, *atype = NULL;
1054   SilcUInt32 len, len2, ttype;
1055   void *type;
1056   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1057
1058   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1059
1060   /* Get Channel ID */
1061   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1062     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1063                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1064     goto out;
1065   }
1066
1067   /* Get the channel entry */
1068   channel = silc_idlist_find_channel_by_id(server->local_list,
1069                                            SILC_ID_GET_ID(id), NULL);
1070   if (!channel) {
1071     channel = silc_idlist_find_channel_by_id(server->global_list,
1072                                              SILC_ID_GET_ID(id), NULL);
1073     if (!channel) {
1074       tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1075       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1076                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1077                                            0, 2, tmp, len);
1078       goto out;
1079     }
1080   }
1081
1082   /* Check whether the sender of this command is on the channel. */
1083   sender = silc_packet_get_context(sock);
1084   if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1085     tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1086     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1087                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1088                                          2, tmp, len);
1089     goto out;
1090   }
1091
1092   /* Check whether the channel is invite-only channel. If yes then the
1093      sender of this command must be at least channel operator. */
1094   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1095       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1096       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1097     tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1098     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1099                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1100                                          0, 2, tmp, len);
1101     goto out;
1102   }
1103
1104   /* Get destination client ID */
1105   if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
1106     SilcBool resolve;
1107
1108     /* Get the client entry */
1109     dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
1110                                     FALSE, &resolve);
1111     if (!dest) {
1112       if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1113         tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1114         silc_server_command_send_status_data(
1115                                         cmd, SILC_COMMAND_INVITE,
1116                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1117                                         2, tmp, len);
1118         goto out;
1119       }
1120
1121       /* The client info is being resolved. Reprocess this packet after
1122          receiving the reply to the query. */
1123       silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1124                                   server->cmd_ident,
1125                                   silc_server_command_invite,
1126                                   silc_server_command_dup(cmd));
1127       cmd->pending = TRUE;
1128       goto out;
1129     }
1130
1131     /* Check whether the requested client is already on the channel. */
1132     if (silc_server_client_on_channel(dest, channel, NULL)) {
1133       tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1134       atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1135       silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1136                                             SILC_STATUS_ERR_USER_ON_CHANNEL,
1137                                             0, 2, tmp, len,
1138                                             3, atype, len2);
1139       goto out;
1140     }
1141
1142     /* Get route to the client */
1143     dest_sock = silc_server_get_client_route(server, NULL, 0,
1144                                              SILC_ID_GET_ID(id2),
1145                                              &idata, NULL);
1146     if (!dest_sock) {
1147       tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1148       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1149                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1150                                            0, 2, tmp, len);
1151       goto out;
1152     }
1153
1154     /* Add the client to the invite list */
1155
1156     /* Allocate hash table for invite list if it doesn't exist yet */
1157     if (!channel->invite_list)
1158       channel->invite_list =
1159         silc_hash_table_alloc(0, silc_hash_ptr,
1160                               NULL, NULL, NULL,
1161                               silc_server_inviteban_destruct, channel, TRUE);
1162
1163     /* Check if the ID is in the list already */
1164     tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1165     silc_hash_table_list(channel->invite_list, &htl);
1166     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1167       if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) {
1168         tmp = NULL;
1169         break;
1170       }
1171     }
1172     silc_hash_table_list_reset(&htl);
1173
1174     /* Add new Client ID to invite list */
1175     if (tmp) {
1176       list = silc_buffer_alloc_size(len);
1177       silc_buffer_put(list, tmp, len);
1178       silc_hash_table_add(channel->invite_list, (void *)3, list);
1179     }
1180
1181     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1182       /* Send notify to the client that is invited to the channel */
1183       SilcBuffer idp, idp2;
1184       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1185       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1186       silc_server_send_notify_dest(server, dest_sock, FALSE,
1187                                    SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
1188                                    SILC_NOTIFY_TYPE_INVITE, 3,
1189                                    idp->data, silc_buffer_len(idp),
1190                                    channel->channel_name,
1191                                    strlen(channel->channel_name),
1192                                    idp2->data, silc_buffer_len(idp2));
1193       silc_buffer_free(idp);
1194       silc_buffer_free(idp2);
1195     }
1196   }
1197
1198   /* Get the invite information */
1199   tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1200   if (tmp && len2 > 2) {
1201     /* Parse the arguments to see they are constructed correctly */
1202     SILC_GET16_MSB(argc, tmp);
1203     args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1204     if (!args) {
1205       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1206                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1207                                             0);
1208       goto out;
1209     }
1210
1211     /* Get the type of action */
1212     atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1213     if (atype && len == 1) {
1214       if (atype[0] == 0x00) {
1215         /* Allocate hash table for invite list if it doesn't exist yet */
1216         if (!channel->invite_list)
1217           channel->invite_list =
1218             silc_hash_table_alloc(0, silc_hash_ptr,
1219                                   NULL, NULL, NULL,
1220                                   silc_server_inviteban_destruct, channel,
1221                                   TRUE);
1222
1223         /* Check for resource limit */
1224         if (silc_hash_table_count(channel->invite_list) > 64) {
1225           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1226                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
1227                                                 0);
1228           goto out;
1229         }
1230       }
1231
1232       /* Now add or delete the information. */
1233       if (!silc_server_inviteban_process(server, channel->invite_list,
1234                                          (SilcUInt8)atype[0], args)) {
1235         silc_server_command_send_status_reply(
1236                                     cmd, SILC_COMMAND_INVITE,
1237                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1238                                     0);
1239         goto out;
1240       }
1241     }
1242     silc_argument_payload_free(args);
1243   }
1244
1245   /* Encode invite list */
1246   list = NULL;
1247   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1248     list = silc_buffer_alloc_size(2);
1249     silc_buffer_format(list,
1250                        SILC_STR_UI_SHORT(silc_hash_table_count(
1251                                           channel->invite_list)),
1252                        SILC_STR_END);
1253     silc_hash_table_list(channel->invite_list, &htl);
1254     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1255       list = silc_argument_payload_encode_one(list, tmp2->data,
1256                                               silc_buffer_len(tmp2),
1257                                               SILC_PTR_TO_32(type));
1258     silc_hash_table_list_reset(&htl);
1259   }
1260
1261   /* The notify is sent to local servers (not clients), and to network. */
1262   if (atype && tmp && len2) {
1263     silc_buffer_set(&alist, tmp, len2);
1264
1265     /* Send to local servers if we are router */
1266     if (server->server_type == SILC_ROUTER) {
1267       SilcBuffer idp, idp2;
1268       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1269       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1270       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1271                                          SILC_NOTIFY_TYPE_INVITE, 5,
1272                                          idp->data, silc_buffer_len(idp),
1273                                          channel->channel_name,
1274                                          strlen(channel->channel_name),
1275                                          idp2->data, silc_buffer_len(idp2),
1276                                          atype, 1,
1277                                          tmp ? alist.data : NULL,
1278                                          tmp ? silc_buffer_len(&alist) : 0);
1279       silc_buffer_free(idp);
1280       silc_buffer_free(idp2);
1281     }
1282
1283     /* Send to network */
1284     silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1285                                    SILC_BROADCAST(server), channel,
1286                                    sender->id, atype,
1287                                    tmp ? &alist : NULL);
1288   }
1289
1290   /* Send invite list back only if the list was modified, or no arguments
1291      was given. */
1292   ttype = 0;
1293   argc = silc_argument_get_arg_num(cmd->args);
1294   if (argc == 1)
1295     ttype = 1;
1296   if (silc_argument_get_arg_type(cmd->args, 3, &len))
1297     ttype = 1;
1298
1299   /* Send command reply */
1300   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1301   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
1302                                  SILC_STATUS_OK, 0, ident, 2,
1303                                  2, tmp, len,
1304                                  3, ttype && list ?
1305                                  list->data : NULL,
1306                                  ttype && list ? silc_buffer_len(list) : 0);
1307   silc_buffer_free(list);
1308
1309  out:
1310   silc_server_command_free(cmd);
1311 }
1312
1313 typedef struct {
1314   SilcPacketStream sock;
1315   char *signoff;
1316 } *QuitInternal;
1317
1318 /* Quits connection to client. This gets called if client won't
1319    close the connection even when it has issued QUIT command. */
1320
1321 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1322 {
1323   SilcServer server = app_context;
1324   QuitInternal q = (QuitInternal)context;
1325   SilcClientEntry client = silc_packet_get_context(q->sock);
1326
1327   if (client) {
1328     /* Free all client specific data, such as client entry and entires
1329        on channels this client may be on. */
1330     silc_server_free_sock_user_data(server, q->sock, q->signoff);
1331     silc_server_close_connection(server, q->sock);
1332   }
1333
1334   silc_packet_stream_unref(q->sock);
1335   silc_free(q->signoff);
1336   silc_free(q);
1337 }
1338
1339 /* Quits SILC session. This is the normal way to disconnect client. */
1340
1341 SILC_SERVER_CMD_FUNC(quit)
1342 {
1343   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1344   SilcServer server = cmd->server;
1345   SilcPacketStream sock = cmd->sock;
1346   SilcClientEntry client = silc_packet_get_context(sock);
1347   QuitInternal q;
1348   unsigned char *tmp = NULL;
1349   SilcUInt32 len = 0;
1350
1351   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1352
1353   if (client->data.conn_type != SILC_CONN_CLIENT)
1354     goto out;
1355
1356   /* Get message */
1357   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1358   if (len > 128)
1359     tmp = NULL;
1360
1361   q = silc_calloc(1, sizeof(*q));
1362   q->sock = sock;
1363   q->signoff = tmp ? strdup(tmp) : NULL;
1364   silc_packet_stream_ref(q->sock);
1365
1366   /* We quit the connection with little timeout */
1367   silc_schedule_task_add_timeout(server->schedule,
1368                                  silc_server_command_quit_cb, (void *)q,
1369                                  0, 200000);
1370
1371  out:
1372   silc_server_command_free(cmd);
1373 }
1374
1375 /* Server side of command KILL. This command is used by router operator
1376    to remove an client from the SILC Network temporarily. */
1377
1378 SILC_SERVER_CMD_FUNC(kill)
1379 {
1380   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1381   SilcServer server = cmd->server;
1382   SilcClientEntry client = silc_packet_get_context(cmd->sock);
1383   SilcClientEntry remote_client;
1384   SilcID id;
1385   unsigned char *tmp, *comment, *auth;
1386   SilcUInt32 tmp_len, tmp_len2, auth_len;
1387
1388   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1389
1390   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
1391     goto out;
1392
1393   /* Get authentication payload if present */
1394   auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1395
1396   if (!auth) {
1397     /* Router operator killing */
1398
1399     /* KILL command works only on router */
1400     if (server->server_type != SILC_ROUTER) {
1401       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1402                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1403       goto out;
1404     }
1405
1406     /* Check whether client has the permissions. */
1407     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1408       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1409                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1410       goto out;
1411     }
1412   }
1413
1414   /* Get the client ID */
1415   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1416     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1417                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1418     goto out;
1419   }
1420
1421   /* Get the client entry */
1422   remote_client = silc_idlist_find_client_by_id(server->local_list,
1423                                                 SILC_ID_GET_ID(id),
1424                                                 TRUE, NULL);
1425   if (!remote_client) {
1426     remote_client = silc_idlist_find_client_by_id(server->global_list,
1427                                                   SILC_ID_GET_ID(id),
1428                                                   TRUE, NULL);
1429     if (!remote_client) {
1430       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1431       silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1432                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1433                                            0, 2, tmp, tmp_len);
1434       goto out;
1435     }
1436   }
1437
1438   /* Get comment */
1439   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1440   if (comment && tmp_len2 > 128) {
1441     tmp_len2 = 128;
1442     comment[tmp_len2 - 1] = '\0';
1443   }
1444
1445   /* If authentication data is provided then verify that killing is
1446      actually allowed */
1447   if (auth && auth_len) {
1448     SilcPacketStream sock;
1449
1450     if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1451       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1452                                             SILC_STATUS_ERR_OPERATION_ALLOWED,
1453                                             0);
1454       goto out;
1455     }
1456
1457     /* Verify the signature */
1458     if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1459                                remote_client->data.public_key, 0,
1460                                server->sha1hash, remote_client->id,
1461                                SILC_ID_CLIENT)) {
1462       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1463                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
1464       goto out;
1465     }
1466
1467     /* Send reply to the sender */
1468     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1469     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1470                                          SILC_STATUS_OK, 0,
1471                                          2, tmp, tmp_len);
1472
1473     /* Do normal signoff for the destination client */
1474     sock = remote_client->connection;
1475
1476     if (sock)
1477       silc_packet_stream_ref(sock);
1478
1479     silc_server_remove_from_channels(server, NULL, remote_client,
1480                                      TRUE, (char *)"Killed", TRUE, TRUE);
1481     silc_server_free_sock_user_data(server, sock, comment ? comment :
1482                                     (unsigned char *)"Killed");
1483     if (sock) {
1484       silc_packet_set_context(sock, NULL);
1485       silc_server_close_connection(server, sock);
1486       silc_packet_stream_unref(sock);
1487     }
1488   } else {
1489     /* Router operator killing */
1490
1491     /* Send reply to the sender */
1492     tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1493     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1494                                          SILC_STATUS_OK, 0,
1495                                          2, tmp, tmp_len);
1496
1497     /* Check if anyone is watching this nickname */
1498     if (server->server_type == SILC_ROUTER)
1499       silc_server_check_watcher_list(server, client, NULL,
1500                                      SILC_NOTIFY_TYPE_KILLED);
1501
1502     /* Now do the killing */
1503     silc_server_kill_client(server, remote_client, comment, client->id,
1504                             SILC_ID_CLIENT);
1505   }
1506
1507  out:
1508   silc_server_command_free(cmd);
1509 }
1510
1511 /* Server side of command INFO. This sends information about us to
1512    the client. If client requested specific server we will send the
1513    command to that server. */
1514
1515 SILC_SERVER_CMD_FUNC(info)
1516 {
1517   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1518   SilcServer server = cmd->server;
1519   SilcBuffer idp;
1520   unsigned char *tmp;
1521   SilcUInt32 tmp_len;
1522   char *dest_server = NULL, *server_info = NULL, *server_name;
1523   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1524   SilcServerEntry entry = NULL;
1525   SilcID id;
1526
1527   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1528
1529   /* Get server name */
1530   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1531   if (dest_server) {
1532     /* Check server name. */
1533     dest_server = silc_identifier_check(dest_server, strlen(dest_server),
1534                                         SILC_STRING_UTF8, 256, &tmp_len);
1535     if (!dest_server) {
1536       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1537                                             SILC_STATUS_ERR_BAD_SERVER, 0);
1538       goto out;
1539     }
1540   }
1541
1542   /* Get Server ID */
1543   if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
1544     /* Check whether we have this server cached */
1545     entry = silc_idlist_find_server_by_id(server->local_list,
1546                                           SILC_ID_GET_ID(id), TRUE, NULL);
1547     if (!entry) {
1548       entry = silc_idlist_find_server_by_id(server->global_list,
1549                                             SILC_ID_GET_ID(id), TRUE, NULL);
1550       if (!entry && server->server_type != SILC_SERVER) {
1551         tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1552         silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1553                                              SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1554                                              0, 2, tmp, tmp_len);
1555         goto out;
1556       }
1557     }
1558   }
1559
1560   if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
1561       (dest_server && !cmd->pending &&
1562        !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
1563     /* Send our reply */
1564     char info_string[256];
1565
1566     memset(info_string, 0, sizeof(info_string));
1567     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), 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
4072   client = silc_idlist_find_client_by_id(server->local_list, client_id,
4073                                          TRUE, NULL);
4074   if (client && client->connection) {
4075     sock = client->connection;
4076
4077     /* Close the connection on our side */
4078     client->router = NULL;
4079     client->connection = NULL;
4080     silc_server_close_connection(server, sock);
4081   }
4082
4083   silc_free(client_id);
4084   silc_free(q);
4085 }
4086
4087 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4088 {
4089   SilcServer server = app_context;
4090   QuitInternal q = (QuitInternal)context;
4091   SilcClientID *client_id = (SilcClientID *)q->sock;
4092   SilcClientEntry client;
4093
4094   client = silc_idlist_find_client_by_id(server->local_list, client_id,
4095                                          TRUE, NULL);
4096   if (client && client->mode & SILC_UMODE_DETACHED) {
4097     SILC_LOG_DEBUG(("Detach timeout"));
4098     silc_server_free_client_data(server, NULL, client, TRUE,
4099                                  "Detach timeout");
4100   }
4101
4102   silc_free(client_id);
4103   silc_free(q);
4104 }
4105
4106 /* Server side of DETACH command.  Detached the client from the network
4107    by closing the connection but preserving the session. */
4108
4109 SILC_SERVER_CMD_FUNC(detach)
4110 {
4111   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4112   SilcServer server = cmd->server;
4113   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4114   QuitInternal q;
4115
4116   if (server->config->detach_disabled) {
4117     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4118                                           SILC_STATUS_ERR_OPERATION_ALLOWED,
4119                                           0);
4120     goto out;
4121   }
4122
4123   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4124     goto out;
4125
4126   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4127
4128   /* Remove operator privileges, since the client may resume in some
4129      other server which to it does not have operator privileges. */
4130   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4131   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4132
4133   /* Send the user mode notify to notify that client is detached */
4134   client->mode |= SILC_UMODE_DETACHED;
4135   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4136   client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4137   client->last_command = 0;
4138   client->fast_command = 0;
4139   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4140                                 SILC_BROADCAST(server), client->id,
4141                                 client->mode);
4142   server->stat.my_detached++;
4143
4144   /* Check if anyone is watching this nickname */
4145   if (server->server_type == SILC_ROUTER)
4146     silc_server_check_watcher_list(server, client, NULL,
4147                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4148
4149   q = silc_calloc(1, sizeof(*q));
4150   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4151   silc_schedule_task_add_timeout(server->schedule,
4152                                  silc_server_command_detach_cb,
4153                                  q, 0, 200000);
4154
4155   if (server->config->detach_timeout) {
4156     q = silc_calloc(1, sizeof(*q));
4157     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4158     silc_schedule_task_add_timeout(server->schedule,
4159                                    silc_server_command_detach_timeout,
4160                                    q, server->config->detach_timeout * 60, 0);
4161   }
4162
4163   /* Send reply to the sender */
4164   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4165                                         SILC_STATUS_OK, 0);
4166
4167  out:
4168   silc_server_command_free(cmd);
4169 }
4170
4171 /* Server side of WATCH command. */
4172
4173 SILC_SERVER_CMD_FUNC(watch)
4174 {
4175   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4176   SilcServer server = cmd->server;
4177   char *add_nick, *del_nick;
4178   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4179   unsigned char hash[SILC_HASH_MAXLEN], *tmp,  *pk, *nick;
4180   SilcClientEntry client;
4181   SilcID id;
4182   SilcUInt16 old_ident;
4183
4184   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4185
4186   if (server->server_type != SILC_ROUTER && !server->standalone) {
4187     if (!cmd->pending) {
4188       /* Send the command to router */
4189       SilcBuffer tmpbuf;
4190
4191       /* If backup receives this from primary, handle it locally */
4192       if (server->server_type == SILC_BACKUP_ROUTER &&
4193           cmd->sock == SILC_PRIMARY_ROUTE(server))
4194         goto process_watch;
4195
4196       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4197
4198       /* Statistics */
4199       cmd->server->stat.commands_sent++;
4200
4201       old_ident = silc_command_get_ident(cmd->payload);
4202       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4203       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4204
4205       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4206                               SILC_PACKET_COMMAND, cmd->packet->flags,
4207                               tmpbuf->data, silc_buffer_len(tmpbuf));
4208
4209       /* Reprocess this packet after received reply from router */
4210       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4211                                   silc_command_get_ident(cmd->payload),
4212                                   silc_server_command_watch,
4213                                   silc_server_command_dup(cmd));
4214       cmd->pending = TRUE;
4215       silc_command_set_ident(cmd->payload, old_ident);
4216       silc_buffer_free(tmpbuf);
4217       goto out;
4218     } else {
4219       SilcServerCommandReplyContext reply = context2;
4220       SilcStatus status;
4221
4222       if (!reply)
4223         goto out;
4224
4225       silc_command_get_status(reply->payload, &status, NULL);
4226
4227       /* Backup router handles the WATCH command also. */
4228       if (server->server_type != SILC_BACKUP_ROUTER ||
4229           SILC_STATUS_IS_ERROR(status)) {
4230         /* Received reply from router, just send same data to the client. */
4231         SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4232         silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4233                                               0);
4234         goto out;
4235       }
4236     }
4237   }
4238
4239   /* We are router and keep the watch list for local cell */
4240  process_watch:
4241
4242   /* Get the client ID */
4243   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4244     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4245                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4246                                           0);
4247     goto out;
4248   }
4249
4250   /* Get the client entry which must be in local list */
4251   client = silc_idlist_find_client_by_id(server->local_list,
4252                                          SILC_ID_GET_ID(id), TRUE, NULL);
4253   if (!client) {
4254     /* Backup checks global list also */
4255     if (server->server_type == SILC_BACKUP_ROUTER)
4256       client = silc_idlist_find_client_by_id(server->global_list,
4257                                              SILC_ID_GET_ID(id), TRUE, NULL);
4258     if (!client) {
4259       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4260       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4261                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4262                                            0, 2, tmp, tmp_len);
4263       goto out;
4264     }
4265   }
4266
4267   /* Take public key for watching by public key */
4268   pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4269
4270   /* Take nickname */
4271   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4272   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4273   if (!add_nick && !del_nick && !pk) {
4274     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4275                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4276                                           0);
4277     goto out;
4278   }
4279
4280   if (add_nick && add_nick_len > 128) {
4281     add_nick_len = 128;
4282     add_nick[add_nick_len - 1] = '\0';
4283   }
4284   if (del_nick && del_nick_len > 128) {
4285     del_nick_len = 128;
4286     del_nick[del_nick_len - 1] = '\0';
4287   }
4288
4289   /* Add new nickname to be watched in our cell */
4290   if (add_nick) {
4291     nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4292                                  &add_nick_len);
4293     if (!nick) {
4294       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4295                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4296       goto out;
4297     }
4298
4299     /* Hash the nick, we have the hash saved, not nicks because we can
4300        do one to one mapping to the nick from Client ID hash this way. */
4301     silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4302
4303     /* Check whether this client is already watching this nickname */
4304     if (silc_hash_table_find_by_context(server->watcher_list, hash,
4305                                         client, NULL)) {
4306       /* Nickname is alredy being watched for this client */
4307       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4308                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
4309                                             0);
4310       silc_free(nick);
4311       goto out;
4312     }
4313
4314     /* Get the nickname from the watcher list and use the same key in
4315        new entries as well.  If key doesn't exist then create it. */
4316     if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4317       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4318
4319     /* Add the client to the watcher list with the specified nickname hash. */
4320     silc_hash_table_add(server->watcher_list, tmp, client);
4321     silc_free(nick);
4322   }
4323
4324   /* Delete nickname from watch list */
4325   if (del_nick) {
4326     nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4327                                  &del_nick_len);
4328     if (!nick) {
4329       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4330                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4331       goto out;
4332     }
4333
4334     /* Hash the nick, we have the hash saved, not nicks because we can
4335        do one to one mapping to the nick from Client ID hash this way. */
4336     silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4337
4338     /* Check that this client is watching for this nickname */
4339     if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4340                                          client, (void *)&tmp)) {
4341       /* Nickname is alredy being watched for this client */
4342       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4343                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4344                                            2, nick, del_nick_len);
4345       silc_free(nick);
4346       goto out;
4347     }
4348
4349     /* Delete the nickname from the watcher list. */
4350     silc_hash_table_del_by_context(server->watcher_list, hash, client);
4351
4352     /* Now check whether there still exists entries with this key, if not
4353        then free the key to not leak memory. */
4354     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4355       silc_free(tmp);
4356     silc_free(nick);
4357   }
4358
4359   /* Add/del public key */
4360   if (pk) {
4361     SilcUInt16 pkargc;
4362     SilcArgumentPayload pkargs;
4363     SilcUInt32 type;
4364     SilcPublicKey public_key, pkkey;
4365
4366     if (pk_len < 2) {
4367       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4368                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4369                                             0);
4370       goto out;
4371     }
4372
4373     /* Get the argument from the Argument List Payload */
4374     SILC_GET16_MSB(pkargc, pk);
4375     pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4376     if (!pkargs) {
4377       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4378                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4379                                             0);
4380       goto out;
4381     }
4382
4383     pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4384     while (pk) {
4385       if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
4386         pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4387         continue;
4388       }
4389       if (type == 0x03)
4390         type = 0x00;
4391
4392       if (type == 0x00) {
4393         /* Add public key to watch list */
4394
4395         /* Check whether this client is already watching this public key */
4396         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4397                                             public_key, client, NULL)) {
4398           silc_pkcs_public_key_free(public_key);
4399           silc_server_command_send_status_reply(
4400                                 cmd, SILC_COMMAND_WATCH,
4401                                 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4402           goto out;
4403         }
4404
4405         /* Get the public key from the watcher list and use the same key in
4406            new entries as well.  If key doesn't exist then create it. */
4407         pkkey = NULL;
4408         if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4409                                   (void *)&pkkey, NULL))
4410           pkkey = public_key;
4411         else
4412           silc_pkcs_public_key_free(public_key);
4413
4414         /* Add the client to the watcher list with the specified public
4415            key. */
4416         silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4417
4418       } else if (type == 0x01) {
4419         /* Delete public key from watch list */
4420
4421         /* Check that this client is watching this public key */
4422         if (silc_hash_table_find_by_context(server->watcher_list_pk,
4423                                             public_key, client,
4424                                             (void *)&pkkey)) {
4425           silc_pkcs_public_key_free(public_key);
4426           silc_server_command_send_status_reply(
4427                                 cmd, SILC_COMMAND_WATCH,
4428                                 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4429           goto out;
4430         }
4431
4432         /* Delete the public key from the watcher list. */
4433         silc_hash_table_del_by_context(server->watcher_list_pk,
4434                                        public_key, client);
4435
4436         /* Now check whether there still exists entries with this key, if
4437            not then free the key to not leak memory. */
4438         if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4439           silc_pkcs_public_key_free(pkkey);
4440         silc_pkcs_public_key_free(public_key);
4441       }
4442
4443       pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4444     }
4445   }
4446
4447   /* Send reply */
4448   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4449                                         SILC_STATUS_OK, 0);
4450
4451   /* Distribute the watch list to backup routers too */
4452   if (server->backup) {
4453     SilcBuffer tmpbuf;
4454
4455     /* Statistics */
4456     cmd->server->stat.commands_sent++;
4457
4458     old_ident = silc_command_get_ident(cmd->payload);
4459     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4460     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4461     silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4462                             SILC_PACKET_COMMAND,
4463                             cmd->packet->flags, tmpbuf->data,
4464                             silc_buffer_len(tmpbuf),
4465                             FALSE, TRUE);
4466     silc_command_set_ident(cmd->payload, old_ident);
4467     silc_buffer_free(tmpbuf);
4468   }
4469
4470  out:
4471   silc_server_command_free(cmd);
4472 }
4473
4474 /* Server side of SILCOPER command. Client uses this comand to obtain router
4475    operator privileges to this router. */
4476
4477 SILC_SERVER_CMD_FUNC(silcoper)
4478 {
4479   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4480   SilcServer server = cmd->server;
4481   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4482   unsigned char *username = NULL, *auth;
4483   SilcUInt32 tmp_len;
4484   SilcServerConfigAdmin *admin;
4485   SilcIDListData idata = (SilcIDListData)client;
4486   SilcBool result = FALSE;
4487   SilcPublicKey cached_key;
4488   const char *hostname, *ip;
4489
4490   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4491     goto out;
4492
4493   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4494
4495   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4496                               NULL, &hostname, &ip, NULL);
4497
4498   if (server->server_type != SILC_ROUTER) {
4499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4500                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4501     goto out;
4502   }
4503
4504   /* Get the username */
4505   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4506   if (!username) {
4507     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4508                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4509                                           0);
4510     goto out;
4511   }
4512
4513   /* Check username */
4514   username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4515                                    &tmp_len);
4516   if (!username) {
4517     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4518                                           SILC_STATUS_ERR_BAD_USERNAME,
4519                                           0);
4520     goto out;
4521   }
4522
4523   /* Get the admin configuration */
4524   admin = silc_server_config_find_admin(server, (char *)ip,
4525                                         username, client->nickname);
4526   if (!admin) {
4527     admin = silc_server_config_find_admin(server, (char *)hostname,
4528                                           username, client->nickname);
4529     if (!admin) {
4530       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4531                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
4532       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4533                      "nickname '%s' from %s", username,
4534                      client->nickname, hostname));
4535       goto out;
4536     }
4537   }
4538
4539   /* Get the authentication payload */
4540   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4541   if (!auth) {
4542     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4543                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4544                                           0);
4545     goto out;
4546   }
4547
4548   /* Verify the authentication data. If both passphrase and public key
4549      is set then try both of them. */
4550   if (admin->passphrase)
4551     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4552                                    admin->passphrase, admin->passphrase_len,
4553                                    idata->hash, client->id, SILC_ID_CLIENT);
4554   if (!result && admin->publickeys) {
4555     cached_key =
4556       silc_server_get_public_key(server,
4557                                  SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4558     if (!cached_key)
4559       goto out;
4560     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4561                                    cached_key, 0, idata->hash,
4562                                    client->id, SILC_ID_CLIENT);
4563   }
4564   if (!result) {
4565     /* Authentication failed */
4566     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4567                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4568     goto out;
4569   }
4570
4571   /* Client is now router operator */
4572   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4573
4574   /* Update statistics */
4575   if (SILC_IS_LOCAL(client))
4576     server->stat.my_router_ops++;
4577   if (server->server_type == SILC_ROUTER)
4578     server->stat.router_ops++;
4579
4580   /* Send UMODE change to primary router */
4581   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4582                                 SILC_BROADCAST(server), client->id,
4583                                 client->mode);
4584
4585   /* Check if anyone is watching this nickname */
4586   if (server->server_type == SILC_ROUTER)
4587     silc_server_check_watcher_list(server, client, NULL,
4588                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4589
4590   /* Send reply to the sender */
4591   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4592                                         SILC_STATUS_OK, 0);
4593
4594  out:
4595   silc_free(username);
4596   silc_server_command_free(cmd);
4597 }
4598
4599 /* Server side of command BAN. This is used to manage the ban list of the
4600    channel. To add clients and remove clients from the ban list. */
4601
4602 SILC_SERVER_CMD_FUNC(ban)
4603 {
4604   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4605   SilcServer server = cmd->server;
4606   SilcClientEntry client = silc_packet_get_context(cmd->sock);
4607   SilcBuffer list, tmp2;
4608   SilcChannelEntry channel;
4609   SilcChannelClientEntry chl;
4610   SilcID id;
4611   unsigned char *tmp_id, *tmp, *atype = NULL;
4612   SilcUInt32 id_len, len, len2;
4613   SilcArgumentPayload args;
4614   SilcHashTableList htl;
4615   void *type;
4616   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4617   SilcBufferStruct blist;
4618
4619   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4620     goto out;
4621
4622   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4623
4624   /* Get Channel ID */
4625   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4626     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4627                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4628     goto out;
4629   }
4630
4631   /* Get channel entry. The server must know about the channel since the
4632      client is expected to be on the channel. */
4633   channel = silc_idlist_find_channel_by_id(server->local_list,
4634                                            SILC_ID_GET_ID(id), NULL);
4635   if (!channel) {
4636     channel = silc_idlist_find_channel_by_id(server->global_list,
4637                                              SILC_ID_GET_ID(id), NULL);
4638     if (!channel) {
4639       tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4640       silc_server_command_send_status_data(
4641                                            cmd, SILC_COMMAND_BAN,
4642                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4643                                            0, 2, tmp_id, id_len);
4644       goto out;
4645     }
4646   }
4647
4648   /* Check whether this client is on the channel */
4649   if (!silc_server_client_on_channel(client, channel, &chl)) {
4650     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4651     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4652                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4653                                          2, tmp_id, id_len);
4654     goto out;
4655   }
4656
4657   /* The client must be at least channel operator. */
4658   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4659     tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4660     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4661                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4662                                          2, tmp_id, id_len);
4663     goto out;
4664   }
4665
4666   /* Get the ban information */
4667   tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4668   if (tmp && len2 > 2) {
4669     /* Parse the arguments to see they are constructed correctly */
4670     SILC_GET16_MSB(argc, tmp);
4671     args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4672     if (!args) {
4673       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4674                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4675                                             0);
4676       goto out;
4677     }
4678
4679     /* Get the type of action */
4680     atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4681     if (atype && len == 1) {
4682       if (atype[0] == 0x00) {
4683         /* Allocate hash table for ban list if it doesn't exist yet */
4684         if (!channel->ban_list)
4685           channel->ban_list =
4686             silc_hash_table_alloc(0, silc_hash_ptr,
4687                                   NULL, NULL, NULL,
4688                                   silc_server_inviteban_destruct, channel,
4689                                   TRUE);
4690
4691         /* Check for resource limit */
4692         if (silc_hash_table_count(channel->ban_list) > 64) {
4693           silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4694                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
4695                                                 0);
4696           goto out;
4697         }
4698       }
4699
4700       /* Now add or delete the information. */
4701       if (!silc_server_inviteban_process(server, channel->ban_list,
4702                                          (SilcUInt8)atype[0], args)) {
4703         silc_server_command_send_status_reply(
4704                                       cmd, SILC_COMMAND_BAN,
4705                                       SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4706                                       0);
4707         goto out;
4708       }
4709     }
4710     silc_argument_payload_free(args);
4711   }
4712
4713   /* Encode ban list */
4714   list = NULL;
4715   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4716     list = silc_buffer_alloc_size(2);
4717     silc_buffer_format(list,
4718                        SILC_STR_UI_SHORT(silc_hash_table_count(
4719                                           channel->ban_list)),
4720                        SILC_STR_END);
4721     silc_hash_table_list(channel->ban_list, &htl);
4722     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4723       list = silc_argument_payload_encode_one(list, tmp2->data,
4724                                               silc_buffer_len(tmp2),
4725                                               SILC_PTR_TO_32(type));
4726     silc_hash_table_list_reset(&htl);
4727   }
4728
4729   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4730
4731   /* Send BAN notify type to local servers (but not clients) and to
4732      network. */
4733   if (atype && tmp && len2) {
4734     silc_buffer_set(&blist, tmp, len2);
4735
4736     /* Send to local servers if we are router */
4737     if (server->server_type == SILC_ROUTER)
4738       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4739                                          SILC_NOTIFY_TYPE_BAN, 3,
4740                                          tmp_id, id_len,
4741                                          atype, 1,
4742                                          tmp ? blist.data : NULL,
4743                                          tmp ? silc_buffer_len(&blist) : 0);
4744
4745     /* Send to network. */
4746     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4747                                 SILC_BROADCAST(server), channel, atype,
4748                                 &blist);
4749   }
4750
4751   /* Send the reply back to the client */
4752   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4753                                  SILC_STATUS_OK, 0, ident, 2,
4754                                  2, tmp_id, id_len,
4755                                  3, list ? list->data : NULL,
4756                                  list ? silc_buffer_len(list) : 0);
4757   silc_buffer_free(list);
4758
4759  out:
4760   silc_server_command_free(cmd);
4761 }
4762
4763 /* Server side command of LEAVE. Removes client from a channel. */
4764
4765 SILC_SERVER_CMD_FUNC(leave)
4766 {
4767   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4768   SilcServer server = cmd->server;
4769   SilcPacketStream sock = cmd->sock;
4770   SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4771   SilcID id;
4772   SilcChannelEntry channel;
4773   SilcUInt32 len;
4774   unsigned char *tmp;
4775
4776   if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4777     goto out;
4778
4779   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4780
4781   /* Get Channel ID */
4782   if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4784                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4785     goto out;
4786   }
4787
4788   /* Get channel entry */
4789   channel = silc_idlist_find_channel_by_id(server->local_list,
4790                                            SILC_ID_GET_ID(id), NULL);
4791   if (!channel) {
4792     channel = silc_idlist_find_channel_by_id(server->global_list,
4793                                              SILC_ID_GET_ID(id), NULL);
4794     if (!channel) {
4795       tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4796       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4797                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4798                                            0, 2, tmp, len);
4799       goto out;
4800     }
4801   }
4802
4803   /* Check whether this client is on the channel */
4804   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4805     tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4806     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4807                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4808                                          2, tmp, len);
4809     goto out;
4810   }
4811
4812   /* Notify routers that they should remove this client from their list
4813      of clients on the channel. Send LEAVE notify type. */
4814   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4815                                 SILC_BROADCAST(server), channel, id_entry->id);
4816
4817   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4818   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4819                                        SILC_STATUS_OK, 0, 2, tmp, len);
4820
4821   /* Remove client from channel */
4822   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4823                                            TRUE))
4824     /* If the channel does not exist anymore we won't send anything */
4825     goto out;
4826
4827   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4828     /* Re-generate channel key */
4829     if (!silc_server_create_channel_key(server, channel, 0))
4830       goto out;
4831
4832     /* Send the channel key */
4833     silc_server_send_channel_key(server, NULL, channel,
4834                                  server->server_type == SILC_ROUTER ?
4835                                  FALSE : !server->standalone);
4836   }
4837
4838  out:
4839   silc_server_command_free(cmd);
4840 }
4841
4842 /* Server side of command USERS. Resolves clients and their USERS currently
4843    joined on the requested channel. The list of Client ID's and their modes
4844    on the channel is sent back. */
4845
4846 SILC_SERVER_CMD_FUNC(users)
4847 {
4848   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4849   SilcServer server = cmd->server;
4850   SilcIDListData idata = silc_packet_get_context(cmd->sock);
4851   SilcChannelEntry channel;
4852   SilcID id;
4853   SilcBuffer idp;
4854   unsigned char *channel_id;
4855   SilcUInt32 channel_id_len;
4856   SilcBuffer client_id_list;
4857   SilcBuffer client_mode_list;
4858   unsigned char lc[4];
4859   SilcUInt32 list_count = 0;
4860   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4861   char *channel_name, *channel_namec = NULL;
4862
4863   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4864
4865   /* Get Channel ID */
4866   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4867
4868   /* Get channel name */
4869   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4870
4871   if (!channel_id && !channel_name) {
4872     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4873                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4874     goto out;
4875   }
4876
4877   /* Check channel name */
4878   if (channel_name) {
4879     channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4880                                             SILC_STRING_UTF8, 256, NULL);
4881     if (!channel_namec) {
4882       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4883                                             SILC_STATUS_ERR_BAD_CHANNEL, 0);
4884       goto out;
4885     }
4886   }
4887
4888   /* Check Channel ID */
4889   if (channel_id) {
4890     if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4891       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4892                                            SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4893                                            2, channel_id, channel_id_len);
4894       goto out;
4895     }
4896   }
4897
4898   /* If we are server and we don't know about this channel we will send
4899      the command to our router. If we know about the channel then we also
4900      have the list of users already. */
4901   if (channel_id)
4902     channel = silc_idlist_find_channel_by_id(server->local_list,
4903                                              SILC_ID_GET_ID(id), NULL);
4904   else
4905     channel = silc_idlist_find_channel_by_name(server->local_list,
4906                                                channel_namec, NULL);
4907
4908   if (!channel || (!server->standalone && (channel->disabled ||
4909                     !channel->users_resolved))) {
4910     if (server->server_type != SILC_ROUTER && !server->standalone &&
4911         !cmd->pending) {
4912       SilcBuffer tmpbuf;
4913
4914       /* Statistics */
4915       cmd->server->stat.commands_sent++;
4916
4917       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4918       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4919
4920       /* Send USERS command */
4921       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4922                               SILC_PACKET_COMMAND, cmd->packet->flags,
4923                               tmpbuf->data, silc_buffer_len(tmpbuf));
4924
4925       /* Reprocess this packet after received reply */
4926       silc_server_command_pending(server, SILC_COMMAND_USERS,
4927                                   silc_command_get_ident(cmd->payload),
4928                                   silc_server_command_users,
4929                                   silc_server_command_dup(cmd));
4930       cmd->pending = TRUE;
4931       silc_command_set_ident(cmd->payload, ident);
4932       silc_buffer_free(tmpbuf);
4933       goto out;
4934     }
4935
4936     /* Check the global list as well. */
4937     if (channel_id)
4938       channel = silc_idlist_find_channel_by_id(server->global_list,
4939                                                SILC_ID_GET_ID(id), NULL);
4940     else
4941       channel = silc_idlist_find_channel_by_name(server->global_list,
4942                                                  channel_namec, NULL);
4943     if (!channel) {
4944       /* Channel really does not exist */
4945       if (channel_id)
4946         silc_server_command_send_status_data(
4947                                     cmd, SILC_COMMAND_USERS,
4948                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4949                                     2, channel_id, channel_id_len);
4950       else
4951         silc_server_command_send_status_data(
4952                                     cmd, SILC_COMMAND_USERS,
4953                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4954                                     2, channel_name, strlen(channel_name));
4955       goto out;
4956     }
4957   }
4958
4959   /* If the channel is private or secret do not send anything, unless the
4960      user requesting this command is on the channel or is server */
4961   if (idata->conn_type == SILC_CONN_CLIENT) {
4962     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4963         && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4964                                           NULL)) {
4965       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4966                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4967                                            2, channel->channel_name,
4968                                            strlen(channel->channel_name));
4969       goto out;
4970     }
4971   }
4972
4973   /* Get the users list */
4974   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4975                                         &client_mode_list, &list_count)) {
4976     list_count = 0;
4977     client_id_list = NULL;
4978     client_mode_list = NULL;
4979   }
4980
4981   /* List count */
4982   SILC_PUT32_MSB(list_count, lc);
4983
4984   /* Send reply */
4985   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4986   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
4987                                  SILC_STATUS_OK, 0, ident, 4,
4988                                  2, idp->data, silc_buffer_len(idp),
4989                                  3, lc, 4,
4990                                  4, client_id_list ?
4991                                  client_id_list->data : NULL,
4992                                  client_id_list ?
4993                                  silc_buffer_len(client_id_list) : 0,
4994                                  5, client_mode_list ?
4995                                  client_mode_list->data : NULL,
4996                                  client_mode_list ?
4997                                  silc_buffer_len(client_mode_list) : 0);
4998   silc_buffer_free(idp);
4999   if (client_id_list)
5000     silc_buffer_free(client_id_list);
5001   if (client_mode_list)
5002     silc_buffer_free(client_mode_list);
5003
5004  out:
5005   silc_free(channel_namec);
5006   silc_server_command_free(cmd);
5007 }
5008
5009 /* Server side of command GETKEY. This fetches the client's public key
5010    from the server where to the client is connected. */
5011
5012 SILC_SERVER_CMD_FUNC(getkey)
5013 {
5014   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5015   SilcServer server = cmd->server;
5016   SilcClientEntry client;
5017   SilcServerEntry server_entry;
5018   SilcClientID client_id;
5019   SilcServerID server_id;
5020   SilcIDPayload idp = NULL;
5021   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5022   unsigned char *tmp;
5023   SilcUInt32 tmp_len;
5024   SilcBuffer pk = NULL;
5025   SilcIdType id_type;
5026   SilcPublicKey public_key;
5027
5028   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5029   if (!tmp) {
5030     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5031                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5032                                           0);
5033     goto out;
5034   }
5035   idp = silc_id_payload_parse(tmp, tmp_len);
5036   if (!idp) {
5037     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5038                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5039                                           0);
5040     goto out;
5041   }
5042
5043   id_type = silc_id_payload_get_type(idp);
5044   if (id_type == SILC_ID_CLIENT) {
5045     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
5046
5047     /* If the client is not found from local list there is no chance it
5048        would be locally connected client so send the command further. */
5049     client = silc_idlist_find_client_by_id(server->local_list,
5050                                            &client_id, TRUE, NULL);
5051     if (!client)
5052       client = silc_idlist_find_client_by_id(server->global_list,
5053                                              &client_id, TRUE, NULL);
5054
5055     if ((!client && !cmd->pending && !server->standalone) ||
5056         (client && !client->connection && !cmd->pending &&
5057          !(client->mode & SILC_UMODE_DETACHED)) ||
5058         (client && !client->data.public_key && !cmd->pending)) {
5059       SilcBuffer tmpbuf;
5060       SilcUInt16 old_ident;
5061       SilcPacketStream dest_sock;
5062
5063       dest_sock = silc_server_get_client_route(server, NULL, 0,
5064                                                &client_id, NULL, NULL);
5065       if (!dest_sock)
5066         goto out;
5067
5068       /* Statistics */
5069       cmd->server->stat.commands_sent++;
5070
5071       old_ident = silc_command_get_ident(cmd->payload);
5072       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5073       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5074
5075       silc_server_packet_send(server, dest_sock,
5076                               SILC_PACKET_COMMAND, cmd->packet->flags,
5077                               tmpbuf->data, silc_buffer_len(tmpbuf));
5078
5079       /* Reprocess this packet after received reply from router */
5080       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5081                                   silc_command_get_ident(cmd->payload),
5082                                   silc_server_command_getkey,
5083                                   silc_server_command_dup(cmd));
5084       cmd->pending = TRUE;
5085       silc_command_set_ident(cmd->payload, old_ident);
5086       silc_buffer_free(tmpbuf);
5087       goto out;
5088     }
5089
5090     if (!client) {
5091       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5092                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5093                                            0, 2, tmp, tmp_len);
5094       goto out;
5095     }
5096
5097     /* The client is locally connected, just get the public key and
5098        send it back. If they key does not exist then do not send it,
5099        send just OK reply */
5100     public_key = client->data.public_key;
5101     if (public_key)
5102       pk = silc_public_key_payload_encode(public_key);
5103   } else if (id_type == SILC_ID_SERVER) {
5104     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5105
5106     /* If the server is not found from local list there is no chance it
5107        would be locally connected server so send the command further. */
5108     server_entry = silc_idlist_find_server_by_id(server->local_list,
5109                                                  &server_id, TRUE, NULL);
5110     if (!server_entry)
5111       server_entry = silc_idlist_find_server_by_id(server->global_list,
5112                                                    &server_id, TRUE, NULL);
5113
5114     if (server_entry != server->id_entry &&
5115         ((!server_entry && !cmd->pending && !server->standalone) ||
5116          (server_entry && !server_entry->connection && !cmd->pending &&
5117           !server->standalone) ||
5118          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5119           !server->standalone))) {
5120       SilcBuffer tmpbuf;
5121       SilcUInt16 old_ident;
5122
5123       /* Statistics */
5124       cmd->server->stat.commands_sent++;
5125
5126       old_ident = silc_command_get_ident(cmd->payload);
5127       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5128       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5129
5130       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5131                               SILC_PACKET_COMMAND, cmd->packet->flags,
5132                               tmpbuf->data, silc_buffer_len(tmpbuf));
5133
5134       /* Reprocess this packet after received reply from router */
5135       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5136                                   silc_command_get_ident(cmd->payload),
5137                                   silc_server_command_getkey,
5138                                   silc_server_command_dup(cmd));
5139       cmd->pending = TRUE;
5140       silc_command_set_ident(cmd->payload, old_ident);
5141       silc_buffer_free(tmpbuf);
5142       goto out;
5143     }
5144
5145     if (!server_entry) {
5146       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5147                                            SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5148                                            0, 2, tmp, tmp_len);
5149       goto out;
5150     }
5151
5152     /* If they key does not exist then do not send it, send just OK reply */
5153     public_key = (!server_entry->data.public_key ?
5154                   (server_entry == server->id_entry ? server->public_key :
5155                    NULL) : server_entry->data.public_key);
5156     if (public_key)
5157       pk = silc_public_key_payload_encode(public_key);
5158   } else {
5159     goto out;
5160   }
5161
5162   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5163   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5164                                  SILC_STATUS_OK, 0, ident, 2,
5165                                  2, tmp, tmp_len,
5166                                  3, pk ? pk->data : NULL,
5167                                  pk ? silc_buffer_len(pk) : 0);
5168
5169  out:
5170   if (idp)
5171     silc_id_payload_free(idp);
5172   silc_buffer_free(pk);
5173   silc_server_command_free(cmd);
5174 }
5175
5176 /* Server side of command SERVICE. */
5177 /* XXX currently this just sends empty reply back */
5178
5179 SILC_SERVER_CMD_FUNC(service)
5180 {
5181   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5182   SilcServer server = cmd->server;
5183   SilcUInt32 tmp_len, auth_len;
5184   unsigned char *service_name, *auth;
5185   SilcBool send_list = FALSE;
5186   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5187
5188   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5189
5190   /* Get requested service */
5191   service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5192   if (service_name && tmp_len) {
5193     /* Verify service name */
5194     if (!silc_identifier_verify(service_name, tmp_len,
5195                                 SILC_STRING_UTF8, 256)) {
5196       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5197                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5198                                             0);
5199       goto out;
5200     }
5201   }
5202
5203   /* Get authentication payload if present */
5204   auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5205   if (auth) {
5206     /* XXX */
5207   }
5208
5209
5210   send_list = TRUE;
5211
5212   /* Send our service list back */
5213   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5214                                  SILC_STATUS_OK, 0, ident, 0);
5215
5216  out:
5217   silc_server_command_free(cmd);
5218 }
5219
5220
5221 /* Private range commands, specific to this implementation */
5222
5223 /* Server side command of CONNECT. Connects us to the specified remote
5224    server or router. */
5225
5226 SILC_SERVER_CMD_FUNC(connect)
5227 {
5228   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5229   SilcServer server = cmd->server;
5230   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5231   unsigned char *tmp, *host;
5232   SilcUInt32 tmp_len;
5233   SilcUInt32 port = SILC_PORT;
5234
5235   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5236     goto out;
5237
5238   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5239
5240   /* Check whether client has the permissions. */
5241   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5242       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5243     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5244                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5245     goto out;
5246   }
5247
5248   if (server->server_type == SILC_ROUTER && !server->backup_router &&
5249       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5250     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5251                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5252     goto out;
5253   }
5254
5255   /* Get the remote server */
5256   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5257   if (!host) {
5258     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5259                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5260                                           0);
5261     goto out;
5262   }
5263
5264   /* Get port */
5265   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5266   if (tmp)
5267     SILC_GET32_MSB(port, tmp);
5268
5269   /* Create the connection. It is done with timeout and is async. */
5270   silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5271
5272   /* Send reply to the sender */
5273   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5274                                         SILC_STATUS_OK, 0);
5275
5276  out:
5277   silc_server_command_free(cmd);
5278 }
5279
5280 /* Server side command of CLOSE. Closes connection to a specified server. */
5281
5282 SILC_SERVER_CMD_FUNC(close)
5283 {
5284   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5285   SilcServer server = cmd->server;
5286   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5287   SilcServerEntry server_entry;
5288   SilcPacketStream sock;
5289   unsigned char *tmp;
5290   SilcUInt32 tmp_len;
5291   unsigned char *name;
5292   SilcUInt32 port = SILC_PORT;
5293
5294   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5295     goto out;
5296
5297   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5298
5299   /* Check whether client has the permissions. */
5300   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5301       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5302     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5303                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5304                                           0);
5305     goto out;
5306   }
5307
5308   /* Get the remote server */
5309   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5310   if (!name) {
5311     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5312                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5313                                           0);
5314     goto out;
5315   }
5316
5317   /* Get port */
5318   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5319   if (tmp)
5320     SILC_GET32_MSB(port, tmp);
5321
5322   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5323                                                  name, port, TRUE, NULL);
5324   if (!server_entry)
5325     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5326                                                    name, port, TRUE, NULL);
5327   if (!server_entry) {
5328     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5329                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5330     goto out;
5331   }
5332
5333   if (server_entry == server->id_entry) {
5334     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5335                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5336     goto out;
5337   }
5338
5339   /* Send reply to the sender */
5340   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5341                                         SILC_STATUS_OK, 0);
5342
5343   /* Close the connection to the server */
5344   sock = server_entry->connection;
5345
5346   if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5347     server->backup_closed = TRUE;
5348     silc_server_backup_del(server, server_entry);
5349   }
5350
5351   server->backup_noswitch = TRUE;
5352   if (server->router == server_entry) {
5353     server->id_entry->router = NULL;
5354     server->router = NULL;
5355     server->standalone = TRUE;
5356   }
5357   silc_server_disconnect_remote(server, sock,
5358                                 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5359                                 "Closed by administrator");
5360   silc_server_free_sock_user_data(server, sock, NULL);
5361   server->backup_noswitch = FALSE;
5362
5363  out:
5364   silc_server_command_free(cmd);
5365 }
5366
5367 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5368    active connections. */
5369
5370 SILC_SERVER_CMD_FUNC(shutdown)
5371 {
5372   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5373   SilcServer server = cmd->server;
5374   SilcClientEntry client = silc_packet_get_context(cmd->sock);
5375
5376   if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5377     goto out;
5378
5379   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5380
5381   /* Check whether client has the permission. */
5382   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5383       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5384     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5385                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5386                                           0);
5387     goto out;
5388   }
5389
5390   /* Send reply to the sender */
5391   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5392                                         SILC_STATUS_OK, 0);
5393
5394   /* Then, gracefully, or not, bring the server down. */
5395   silc_server_stop(server);
5396   exit(0);
5397
5398  out:
5399   silc_server_command_free(cmd);
5400 }