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