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