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