Implemented SilcStatus error argument returning.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2003 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_len2,
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   /* Free all client specific data, such as client entry and entires
1336      on channels this client may be on. */
1337   silc_server_free_client_data(server, q->sock, q->sock->user_data,
1338                                TRUE, q->signoff);
1339   q->sock->user_data = NULL;
1340
1341   /* Close the connection on our side */
1342   silc_server_close_connection(server, q->sock);
1343
1344   silc_socket_free(q->sock);
1345   silc_free(q->signoff);
1346   silc_free(q);
1347 }
1348
1349 /* Quits SILC session. This is the normal way to disconnect client. */
1350
1351 SILC_SERVER_CMD_FUNC(quit)
1352 {
1353   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1354   SilcServer server = cmd->server;
1355   SilcSocketConnection sock = cmd->sock;
1356   QuitInternal q;
1357   unsigned char *tmp = NULL;
1358   SilcUInt32 len = 0;
1359
1360   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1361
1362   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1363     goto out;
1364
1365   /* Get message */
1366   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1367   if (len > 128)
1368     tmp = NULL;
1369
1370   q = silc_calloc(1, sizeof(*q));
1371   q->sock = silc_socket_dup(sock);
1372   q->signoff = tmp ? strdup(tmp) : NULL;
1373
1374   /* We quit the connection with little timeout */
1375   silc_schedule_task_add(server->schedule, sock->sock,
1376                          silc_server_command_quit_cb, (void *)q,
1377                          0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1378
1379  out:
1380   silc_server_command_free(cmd);
1381 }
1382
1383 /* Server side of command KILL. This command is used by router operator
1384    to remove an client from the SILC Network temporarily. */
1385
1386 SILC_SERVER_CMD_FUNC(kill)
1387 {
1388   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1389   SilcServer server = cmd->server;
1390   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1391   SilcClientEntry remote_client;
1392   SilcClientID *client_id = NULL;
1393   unsigned char *tmp, *comment, *auth;
1394   SilcUInt32 tmp_len, tmp_len2, auth_len;
1395
1396   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1397
1398   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1399     goto out;
1400
1401   /* Get authentication payload if present */
1402   auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1403
1404   if (!auth) {
1405     /* Router operator killing */
1406
1407     /* KILL command works only on router */
1408     if (server->server_type != SILC_ROUTER) {
1409       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1410                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1411       goto out;
1412     }
1413
1414     /* Check whether client has the permissions. */
1415     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1416       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1417                                             SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1418       goto out;
1419     }
1420   }
1421
1422   /* Get the client ID */
1423   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1424   if (!tmp) {
1425     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1426                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1427                                           0);
1428     goto out;
1429   }
1430   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1431   if (!client_id) {
1432     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1433                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1434                                          0, 2, tmp, tmp_len);
1435     goto out;
1436   }
1437
1438   /* Get the client entry */
1439   remote_client = silc_idlist_find_client_by_id(server->local_list,
1440                                                 client_id, TRUE, NULL);
1441   if (!remote_client) {
1442     remote_client = silc_idlist_find_client_by_id(server->global_list,
1443                                                   client_id, TRUE, NULL);
1444     if (!remote_client) {
1445       silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1446                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1447                                            0, 2, tmp, tmp_len);
1448       goto out;
1449     }
1450   }
1451
1452   /* Get comment */
1453   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1454   if (comment && tmp_len2 > 128) {
1455     tmp_len2 = 128;
1456     comment[127] = '\0';
1457   }
1458
1459   /* If authentication data is provided then verify that killing is
1460      actually allowed */
1461   if (auth && auth_len) {
1462     SilcSocketConnection sock;
1463
1464     if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1465       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1466                                             SILC_STATUS_ERR_OPERATION_ALLOWED,
1467                                             0);
1468       goto out;
1469     }
1470
1471     /* Verify the signature */
1472     if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1473                                remote_client->data.public_key, 0,
1474                                server->sha1hash, remote_client->id,
1475                                SILC_ID_CLIENT)) {
1476       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1477                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
1478       goto out;
1479     }
1480
1481     /* Send reply to the sender */
1482     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1483                                          SILC_STATUS_OK, 0,
1484                                          2, tmp, tmp_len);
1485
1486     /* Do normal signoff for the destination client */
1487     sock = remote_client->connection;
1488     silc_server_remove_from_channels(server, NULL, remote_client,
1489                                      TRUE, (char *)"Killed", TRUE, TRUE);
1490     silc_server_free_client_data(server, NULL, remote_client, TRUE,
1491                                  comment ? comment :
1492                                  (unsigned char *)"Killed");
1493     if (sock)
1494       silc_server_close_connection(server, sock);
1495   } else {
1496     /* Router operator killing */
1497
1498     /* Send reply to the sender */
1499     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1500                                          SILC_STATUS_OK, 0,
1501                                          2, tmp, tmp_len);
1502
1503     /* Check if anyone is watching this nickname */
1504     if (server->server_type == SILC_ROUTER)
1505       silc_server_check_watcher_list(server, client, NULL,
1506                                      SILC_NOTIFY_TYPE_KILLED);
1507
1508     /* Now do the killing */
1509     silc_server_kill_client(server, remote_client, comment, client->id,
1510                             SILC_ID_CLIENT);
1511   }
1512
1513  out:
1514   silc_free(client_id);
1515   silc_server_command_free(cmd);
1516 }
1517
1518 /* Server side of command INFO. This sends information about us to
1519    the client. If client requested specific server we will send the
1520    command to that server. */
1521
1522 SILC_SERVER_CMD_FUNC(info)
1523 {
1524   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1525   SilcServer server = cmd->server;
1526   SilcBuffer packet, idp;
1527   unsigned char *tmp;
1528   SilcUInt32 tmp_len;
1529   char *dest_server, *server_info = NULL, *server_name;
1530   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1531   SilcServerEntry entry = NULL;
1532   SilcServerID *server_id = NULL;
1533
1534   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1535
1536   /* Get server name */
1537   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1538
1539   /* Get Server ID */
1540   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1541   if (tmp) {
1542     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1543     if (!server_id) {
1544       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1545                                             SILC_STATUS_ERR_NO_SERVER_ID, 0);
1546       goto out;
1547     }
1548   }
1549
1550   if (server_id) {
1551     /* Check whether we have this server cached */
1552     entry = silc_idlist_find_server_by_id(server->local_list,
1553                                           server_id, TRUE, NULL);
1554     if (!entry) {
1555       entry = silc_idlist_find_server_by_id(server->global_list,
1556                                             server_id, TRUE, NULL);
1557       if (!entry && server->server_type != SILC_SERVER) {
1558         silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1559                                              SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1560                                              0, 2, tmp, tmp_len);
1561         goto out;
1562       }
1563     }
1564   }
1565
1566   /* Some buggy servers has sent request to router about themselves. */
1567   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1568     goto out;
1569
1570   if ((!dest_server && !server_id && !entry) || (entry &&
1571                                                  entry == server->id_entry) ||
1572       (dest_server && !cmd->pending &&
1573        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1574     /* Send our reply */
1575     char info_string[256];
1576
1577     memset(info_string, 0, sizeof(info_string));
1578     snprintf(info_string, sizeof(info_string),
1579              "location: %s server: %s admin: %s <%s>",
1580              server->config->server_info->location,
1581              server->config->server_info->server_type,
1582              server->config->server_info->admin,
1583              server->config->server_info->email);
1584
1585     server_info = info_string;
1586     entry = server->id_entry;
1587   } else {
1588     /* Check whether we have this server cached */
1589     if (!entry && dest_server) {
1590       entry = silc_idlist_find_server_by_name(server->global_list,
1591                                               dest_server, TRUE, NULL);
1592       if (!entry) {
1593         entry = silc_idlist_find_server_by_name(server->local_list,
1594                                                 dest_server, TRUE, NULL);
1595       }
1596     }
1597
1598     if (!cmd->pending &&
1599         server->server_type != SILC_SERVER && entry && !entry->server_info) {
1600       /* Send to the server */
1601       SilcBuffer tmpbuf;
1602       SilcUInt16 old_ident;
1603
1604       old_ident = silc_command_get_ident(cmd->payload);
1605       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1606       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1607
1608       silc_server_packet_send(server, entry->connection,
1609                               SILC_PACKET_COMMAND, cmd->packet->flags,
1610                               tmpbuf->data, tmpbuf->len, TRUE);
1611
1612       /* Reprocess this packet after received reply from router */
1613       silc_server_command_pending(server, SILC_COMMAND_INFO,
1614                                   silc_command_get_ident(cmd->payload),
1615                                   silc_server_command_info,
1616                                   silc_server_command_dup(cmd));
1617       cmd->pending = TRUE;
1618       silc_command_set_ident(cmd->payload, old_ident);
1619       silc_buffer_free(tmpbuf);
1620       goto out;
1621     }
1622
1623     if (!entry && !cmd->pending && !server->standalone) {
1624       /* Send to the primary router */
1625       SilcBuffer tmpbuf;
1626       SilcUInt16 old_ident;
1627
1628       old_ident = silc_command_get_ident(cmd->payload);
1629       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1630       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1631
1632       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1633                               SILC_PACKET_COMMAND, cmd->packet->flags,
1634                               tmpbuf->data, tmpbuf->len, TRUE);
1635
1636       /* Reprocess this packet after received reply from router */
1637       silc_server_command_pending(server, SILC_COMMAND_INFO,
1638                                   silc_command_get_ident(cmd->payload),
1639                                   silc_server_command_info,
1640                                   silc_server_command_dup(cmd));
1641       cmd->pending = TRUE;
1642       silc_command_set_ident(cmd->payload, old_ident);
1643       silc_buffer_free(tmpbuf);
1644       goto out;
1645     }
1646   }
1647
1648   silc_free(server_id);
1649
1650   if (!entry) {
1651     if (dest_server)
1652       silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1653                                            SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1654                                            2, dest_server,
1655                                            strlen(dest_server));
1656     goto out;
1657   }
1658
1659   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1660   if (!server_info)
1661     server_info = entry->server_info;
1662   server_name = entry->server_name;
1663
1664   /* Send the reply */
1665   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1666                                                 SILC_STATUS_OK, 0, ident, 3,
1667                                                 2, idp->data, idp->len,
1668                                                 3, server_name,
1669                                                 strlen(server_name),
1670                                                 4, server_info,
1671                                                 server_info ?
1672                                                 strlen(server_info) : 0);
1673   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1674                           packet->data, packet->len, FALSE);
1675
1676   silc_buffer_free(packet);
1677   silc_buffer_free(idp);
1678
1679  out:
1680   silc_server_command_free(cmd);
1681 }
1682
1683 /* Server side of command PING. This just replies to the ping. */
1684
1685 SILC_SERVER_CMD_FUNC(ping)
1686 {
1687   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1688   SilcServer server = cmd->server;
1689   SilcUInt32 tmp_len;
1690   unsigned char *tmp;
1691   SilcServerID *server_id = NULL;
1692
1693   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1694
1695   /* Get Server ID */
1696   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1697   if (!tmp) {
1698     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1699                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1700                                           0);
1701     goto out;
1702   }
1703   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1704   if (!server_id)
1705     goto out;
1706
1707   if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1708     /* Send our reply */
1709     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1710                                           SILC_STATUS_OK, 0);
1711   } else {
1712     silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1713                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1714                                          2, tmp, tmp_len);
1715     goto out;
1716   }
1717
1718  out:
1719   silc_free(server_id);
1720   silc_server_command_free(cmd);
1721 }
1722
1723 /* Server side of command STATS. */
1724
1725 SILC_SERVER_CMD_FUNC(stats)
1726 {
1727   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1728   SilcServer server = cmd->server;
1729   SilcServerID *server_id;
1730   unsigned char *tmp;
1731   SilcUInt32 tmp_len;
1732   SilcBuffer packet, stats;
1733   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1734   SilcUInt32 uptime;
1735
1736   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1737
1738   /* Get Server ID */
1739   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1740   if (!tmp) {
1741     silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1742                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
1743     goto out;
1744   }
1745   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1746   if (!server_id)
1747     goto out;
1748
1749   /* The ID must be ours */
1750   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1751     silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1752                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1753                                          2, tmp, tmp_len);
1754     silc_free(server_id);
1755     goto out;
1756   }
1757   silc_free(server_id);
1758
1759   /* If we are router then just send everything we got. If we are normal
1760      server then we'll send this to our router to get all the latest
1761      statistical information. */
1762   if (!cmd->pending && server->server_type != SILC_ROUTER &&
1763       !server->standalone) {
1764     /* Send request to our router */
1765     SilcBuffer idp = silc_id_payload_encode(server->router->id,
1766                                             SILC_ID_SERVER);
1767     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1768                                             ++server->cmd_ident, 1,
1769                                             1, idp->data, idp->len);
1770     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1771                             SILC_PACKET_COMMAND, 0, packet->data,
1772                             packet->len, FALSE);
1773
1774     /* Reprocess this packet after received reply from router */
1775     silc_server_command_pending(server, SILC_COMMAND_STATS,
1776                                 server->cmd_ident,
1777                                 silc_server_command_stats,
1778                                 silc_server_command_dup(cmd));
1779     cmd->pending = TRUE;
1780     silc_buffer_free(packet);
1781     silc_buffer_free(idp);
1782     goto out;
1783   }
1784
1785   /* Send our reply to sender */
1786   uptime = time(NULL) - server->starttime;
1787
1788   stats = silc_buffer_alloc_size(60);
1789   silc_buffer_format(stats,
1790                      SILC_STR_UI_INT(server->starttime),
1791                      SILC_STR_UI_INT(uptime),
1792                      SILC_STR_UI_INT(server->stat.my_clients),
1793                      SILC_STR_UI_INT(server->stat.my_channels),
1794                      SILC_STR_UI_INT(server->stat.my_server_ops),
1795                      SILC_STR_UI_INT(server->stat.my_router_ops),
1796                      SILC_STR_UI_INT(server->stat.cell_clients),
1797                      SILC_STR_UI_INT(server->stat.cell_channels),
1798                      SILC_STR_UI_INT(server->stat.cell_servers),
1799                      SILC_STR_UI_INT(server->stat.clients),
1800                      SILC_STR_UI_INT(server->stat.channels),
1801                      SILC_STR_UI_INT(server->stat.servers),
1802                      SILC_STR_UI_INT(server->stat.routers),
1803                      SILC_STR_UI_INT(server->stat.server_ops),
1804                      SILC_STR_UI_INT(server->stat.router_ops),
1805                      SILC_STR_END);
1806
1807   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1808                                                 SILC_STATUS_OK, 0, ident, 2,
1809                                                 2, tmp, tmp_len,
1810                                                 3, stats->data, stats->len);
1811   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1812                           0, packet->data, packet->len, FALSE);
1813   silc_buffer_free(packet);
1814   silc_buffer_free(stats);
1815
1816  out:
1817   silc_server_command_free(cmd);
1818 }
1819
1820 /* Internal routine to join channel. The channel sent to this function
1821    has been either created or resolved from ID lists. This joins the sent
1822    client to the channel. */
1823
1824 static void silc_server_command_join_channel(SilcServer server,
1825                                              SilcServerCommandContext cmd,
1826                                              SilcChannelEntry channel,
1827                                              SilcClientID *client_id,
1828                                              bool created,
1829                                              bool create_key,
1830                                              SilcUInt32 umode,
1831                                              const unsigned char *auth,
1832                                              SilcUInt32 auth_len,
1833                                              const unsigned char *cauth,
1834                                              SilcUInt32 cauth_len)
1835 {
1836   SilcSocketConnection sock = cmd->sock;
1837   unsigned char *tmp;
1838   SilcUInt32 tmp_len, user_count;
1839   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1840   SilcClientEntry client;
1841   SilcChannelClientEntry chl;
1842   SilcBuffer reply, chidp, clidp, keyp = NULL;
1843   SilcBuffer user_list, mode_list, invite_list, ban_list;
1844   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1845   char check[512], check2[512];
1846   bool founder = FALSE;
1847   bool resolve;
1848   SilcBuffer fkey = NULL, chpklist = NULL;
1849   const char *cipher;
1850
1851   SILC_LOG_DEBUG(("Joining client to channel"));
1852
1853   if (!channel)
1854     return;
1855
1856   /* Get the client entry */
1857   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1858     client = (SilcClientEntry)sock->user_data;
1859     if (!client)
1860       return;
1861   } else {
1862     client = silc_server_query_client(server, client_id, FALSE,
1863                                       &resolve);
1864     if (!client) {
1865       if (!resolve || cmd->pending) {
1866         silc_server_command_send_status_reply(
1867                                          cmd, SILC_COMMAND_JOIN,
1868                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1869         goto out;
1870       }
1871
1872       /* The client info is being resolved. Reprocess this packet after
1873          receiving the reply to the query. */
1874       silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1875                                   server->cmd_ident,
1876                                   silc_server_command_join,
1877                                   silc_server_command_dup(cmd));
1878       cmd->pending = TRUE;
1879       goto out;
1880     }
1881
1882     if (!client->data.public_key &&
1883         (auth || cauth || channel->ban_list ||
1884          (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1885       if (cmd->pending == 2)
1886         goto out;
1887
1888       /* We must retrieve the client's public key by sending
1889          GETKEY command. Reprocess this packet after receiving the key */
1890       clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1891       silc_server_send_command(server, cmd->sock,
1892                                SILC_COMMAND_GETKEY, ++server->cmd_ident,
1893                                1, 1, clidp->data, clidp->len);
1894       silc_buffer_free(clidp);
1895       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1896                                   server->cmd_ident,
1897                                   silc_server_command_join,
1898                                   silc_server_command_dup(cmd));
1899       cmd->pending = 2;
1900       goto out;
1901     }
1902
1903     cmd->pending = FALSE;
1904   }
1905
1906   /*
1907    * Check founder auth payload if provided.  If client can gain founder
1908    * privileges it can override various conditions on joining the channel,
1909    * and can have directly the founder mode set on the channel.
1910    */
1911   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1912     SilcIDListData idata = (SilcIDListData)client;
1913     SilcChannelClientEntry chl2;
1914     SilcHashTableList htl;
1915
1916     if (channel->founder_key && idata->public_key &&
1917         silc_pkcs_public_key_compare(channel->founder_key,
1918                                      idata->public_key)) {
1919       /* Check whether the client is to become founder */
1920       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1921                                 channel->founder_key, 0, server->sha1hash,
1922                                 client->id, SILC_ID_CLIENT)) {
1923
1924         /* There cannot be anyone else as founder on the channel now.  This
1925            client is definitely the founder due to this authentication */
1926         silc_hash_table_list(channel->user_list, &htl);
1927         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1928           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1929             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1930             silc_server_force_cumode_change(server, NULL, channel, chl2,
1931                                             chl2->mode);
1932             break;
1933           }
1934         silc_hash_table_list_reset(&htl);
1935
1936         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1937         founder = TRUE;
1938       }
1939     }
1940   }
1941
1942   /*
1943    * Check channel modes
1944    */
1945
1946   if (!umode) {
1947     memset(check, 0, sizeof(check));
1948     memset(check2, 0, sizeof(check2));
1949     silc_strncat(check, sizeof(check),
1950                  client->nickname, strlen(client->nickname));
1951     silc_strncat(check, sizeof(check), "!", 1);
1952     silc_strncat(check, sizeof(check),
1953                  client->username, strlen(client->username));
1954     if (!strchr(client->username, '@')) {
1955       silc_strncat(check, sizeof(check), "@", 1);
1956       silc_strncat(check, sizeof(check),
1957                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1958     }
1959
1960     silc_strncat(check2, sizeof(check2),
1961                  client->nickname, strlen(client->nickname));
1962     if (!strchr(client->nickname, '@')) {
1963       silc_strncat(check2, sizeof(check2), "@", 1);
1964       silc_strncat(check2, sizeof(check2),
1965                    server->server_name, strlen(server->server_name));
1966     }
1967     silc_strncat(check2, sizeof(check2), "!", 1);
1968     silc_strncat(check2, sizeof(check2),
1969                  client->username, strlen(client->username));
1970     if (!strchr(client->username, '@')) {
1971       silc_strncat(check2, sizeof(check2), "@", 1);
1972       silc_strncat(check2, sizeof(check2),
1973                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1974     }
1975
1976     /* Check invite list if channel is invite-only channel */
1977     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1978       if (!channel->invite_list ||
1979           !silc_hash_table_count(channel->invite_list) ||
1980           (!silc_server_inviteban_match(server, channel->invite_list,
1981                                         3, client->id) &&
1982            !silc_server_inviteban_match(server, channel->invite_list,
1983                                         2, client->data.public_key) &&
1984            !silc_server_inviteban_match(server, channel->invite_list,
1985                                         1, client->nickname) &&
1986            !silc_server_inviteban_match(server, channel->invite_list,
1987                                         1, check) &&
1988            !silc_server_inviteban_match(server, channel->invite_list,
1989                                         1, check2))) {
1990         chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1991         silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
1992                                              SILC_STATUS_ERR_NOT_INVITED, 0,
1993                                              2, chidp->data, chidp->len);
1994         silc_buffer_free(chidp);
1995         goto out;
1996       }
1997     }
1998
1999     /* Check ban list if it exists. If the client's nickname, server,
2000        username and/or hostname is in the ban list the access to the
2001        channel is denied. */
2002     if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2003       if (silc_server_inviteban_match(server, channel->ban_list,
2004                                       3, client->id) ||
2005           silc_server_inviteban_match(server, channel->ban_list,
2006                                       2, client->data.public_key) ||
2007           silc_server_inviteban_match(server, channel->ban_list,
2008                                       1, client->nickname) ||
2009           silc_server_inviteban_match(server, channel->ban_list,
2010                                       1, check) ||
2011           silc_server_inviteban_match(server, channel->ban_list,
2012                                       1, check2)) {
2013         chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2014         silc_server_command_send_status_data(
2015                                       cmd, SILC_COMMAND_JOIN,
2016                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2017                                       2, chidp->data, chidp->len);
2018         silc_buffer_free(chidp);
2019         goto out;
2020       }
2021     }
2022
2023     /* Check user count limit if set. */
2024     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2025       if (silc_hash_table_count(channel->user_list) + 1 >
2026           channel->user_limit) {
2027         chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2028         silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2029                                              SILC_STATUS_ERR_CHANNEL_IS_FULL,
2030                                              0, 2, chidp->data, chidp->len);
2031         silc_buffer_free(chidp);
2032         goto out;
2033       }
2034     }
2035   }
2036
2037   /* Check the channel passphrase if set. */
2038   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2039     /* Get passphrase */
2040     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2041     if (tmp)
2042       passphrase = silc_memdup(tmp, tmp_len);
2043
2044     if (!passphrase || !channel->passphrase ||
2045         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2046       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2047                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
2048       goto out;
2049     }
2050   }
2051
2052   /* Verify channel authentication with channel public keys if set. */
2053   if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2054     if (!silc_server_verify_channel_auth(server, channel, client->id,
2055                                          cauth, cauth_len)) {
2056       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2057                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2058       goto out;
2059     }
2060   }
2061
2062   /*
2063    * Client is allowed to join to the channel. Make it happen.
2064    */
2065
2066   /* Check whether the client already is on the channel */
2067   if (silc_server_client_on_channel(client, channel, NULL)) {
2068     clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2069     chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2070     silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2071                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2072                                           2, clidp->data, clidp->len,
2073                                           3, chidp->data, chidp->len);
2074     silc_buffer_free(clidp);
2075     silc_buffer_free(chidp);
2076     goto out;
2077   }
2078
2079   /* Generate new channel key as protocol dictates */
2080   if (create_key) {
2081     if (!silc_server_create_channel_key(server, channel, 0))
2082       goto out;
2083
2084     /* Send the channel key. This is broadcasted to the channel but is not
2085        sent to the client who is joining to the channel. */
2086     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2087       silc_server_send_channel_key(server, NULL, channel,
2088                                    server->server_type == SILC_ROUTER ?
2089                                    FALSE : !server->standalone);
2090   }
2091
2092   /* Join the client to the channel by adding it to channel's user list.
2093      Add also the channel to client entry's channels list for fast cross-
2094      referencing. */
2095   chl = silc_calloc(1, sizeof(*chl));
2096   chl->mode = umode;
2097   chl->client = client;
2098   chl->channel = channel;
2099   silc_hash_table_add(channel->user_list, client, chl);
2100   silc_hash_table_add(client->channels, channel, chl);
2101   channel->user_count++;
2102   channel->disabled = FALSE;
2103
2104   /* Get users on the channel */
2105   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2106                                    &user_count);
2107
2108   /* Encode Client ID Payload of the original client who wants to join */
2109   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2110
2111   /* Encode command reply packet */
2112   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2113   SILC_PUT32_MSB(channel->mode, mode);
2114   SILC_PUT32_MSB(created, tmp2);
2115   SILC_PUT32_MSB(user_count, tmp3);
2116
2117   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2118     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2119     cipher = silc_cipher_get_name(channel->channel_key);
2120     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2121                                                            SILC_ID_CHANNEL),
2122                                            tmp,
2123                                            strlen(cipher), cipher,
2124                                            channel->key_len / 8, channel->key);
2125     silc_free(tmp);
2126   }
2127
2128   if (channel->founder_key)
2129     fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2130
2131   /* Encode invite list */
2132   invite_list = NULL;
2133   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2134     SilcHashTableList htl;
2135
2136     invite_list = silc_buffer_alloc_size(2);
2137     silc_buffer_format(invite_list,
2138                        SILC_STR_UI_SHORT(silc_hash_table_count(
2139                                           channel->invite_list)),
2140                        SILC_STR_END);
2141
2142     silc_hash_table_list(channel->invite_list, &htl);
2143     while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
2144       invite_list = silc_argument_payload_encode_one(invite_list,
2145                                                      reply->data,
2146                                                      reply->len, tmp_len);
2147     silc_hash_table_list_reset(&htl);
2148   }
2149
2150   /* Encode ban list */
2151   ban_list = NULL;
2152   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2153     SilcHashTableList htl;
2154
2155     ban_list = silc_buffer_alloc_size(2);
2156     silc_buffer_format(ban_list,
2157                        SILC_STR_UI_SHORT(silc_hash_table_count(
2158                                           channel->ban_list)),
2159                        SILC_STR_END);
2160
2161     silc_hash_table_list(channel->ban_list, &htl);
2162     while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
2163       ban_list = silc_argument_payload_encode_one(ban_list,
2164                                                   reply->data,
2165                                                   reply->len, tmp_len);
2166     silc_hash_table_list_reset(&htl);
2167   }
2168
2169   if (channel->channel_pubkeys)
2170     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2171
2172   reply =
2173     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2174                                          SILC_STATUS_OK, 0, ident, 15,
2175                                          2, channel->channel_name,
2176                                          strlen(channel->channel_name),
2177                                          3, chidp->data, chidp->len,
2178                                          4, clidp->data, clidp->len,
2179                                          5, mode, 4,
2180                                          6, tmp2, 4,
2181                                          7, keyp ? keyp->data : NULL,
2182                                          keyp ? keyp->len : 0,
2183                                          8, ban_list ? ban_list->data : NULL,
2184                                          ban_list ? ban_list->len : 0,
2185                                          9, invite_list ? invite_list->data :
2186                                          NULL,
2187                                          invite_list ? invite_list->len : 0,
2188                                          10, channel->topic,
2189                                          channel->topic ?
2190                                          strlen(channel->topic) : 0,
2191                                          11, silc_hmac_get_name(channel->hmac),
2192                                          strlen(silc_hmac_get_name(channel->
2193                                                                    hmac)),
2194                                          12, tmp3, 4,
2195                                          13, user_list->data, user_list->len,
2196                                          14, mode_list->data,
2197                                          mode_list->len,
2198                                          15, fkey ? fkey->data : NULL,
2199                                          fkey ? fkey->len : 0,
2200                                          16, chpklist ? chpklist->data : NULL,
2201                                          chpklist ? chpklist->len : 0);
2202
2203   /* Send command reply */
2204   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2205                           reply->data, reply->len, FALSE);
2206
2207   /* Send JOIN notify to locally connected clients on the channel. If
2208      we are normal server then router will send or have sent JOIN notify
2209      already. However since we've added the client already to our channel
2210      we'll ignore it (in packet_receive.c) so we must send it here. If
2211      we are router then this will send it to local clients and local
2212      servers. */
2213   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2214   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2215                                      SILC_NOTIFY_TYPE_JOIN, 2,
2216                                      clidp->data, clidp->len,
2217                                      chidp->data, chidp->len);
2218
2219   /* Update statistics */
2220   server->stat.my_chanclients++;
2221   if (server->server_type == SILC_ROUTER) {
2222     server->stat.cell_chanclients++;
2223     server->stat.chanclients++;
2224   }
2225
2226   if (!cmd->pending) {
2227     /* Send JOIN notify packet to our primary router */
2228     silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2229                                  SILC_BROADCAST(server), channel, client->id);
2230
2231     if (keyp)
2232       /* Distribute the channel key to all backup routers. */
2233       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2234                               keyp->data, keyp->len, FALSE, TRUE);
2235
2236     /* If client became founder by providing correct founder auth data
2237        notify the mode change to the channel. */
2238     if (founder) {
2239       SILC_PUT32_MSB(chl->mode, mode);
2240       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2241       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2242                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2243                                          clidp->data, clidp->len,
2244                                          mode, 4, clidp->data, clidp->len,
2245                                          fkey ? fkey->data : NULL,
2246                                          fkey ? fkey->len : 0);
2247     }
2248   }
2249
2250   /* Set CUMODE notify type to network */
2251   if (founder)
2252     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2253                                    SILC_BROADCAST(server), channel,
2254                                    chl->mode, client->id, SILC_ID_CLIENT,
2255                                    client->id, channel->founder_key);
2256
2257   silc_buffer_free(reply);
2258   silc_buffer_free(clidp);
2259   silc_buffer_free(chidp);
2260   silc_buffer_free(keyp);
2261   silc_buffer_free(user_list);
2262   silc_buffer_free(mode_list);
2263   silc_buffer_free(fkey);
2264   silc_buffer_free(chpklist);
2265   silc_buffer_free(invite_list);
2266   silc_buffer_free(ban_list);
2267
2268  out:
2269   if (passphrase)
2270     memset(passphrase, 0, strlen(passphrase));
2271   silc_free(passphrase);
2272 }
2273
2274 /* Server side of command JOIN. Joins client into requested channel. If
2275    the channel does not exist it will be created. */
2276
2277 SILC_SERVER_CMD_FUNC(join)
2278 {
2279   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2280   SilcServer server = cmd->server;
2281   unsigned char *auth, *cauth;
2282   SilcUInt32 tmp_len, auth_len, cauth_len;
2283   char *tmp, *channel_name = NULL, *cipher, *hmac;
2284   SilcChannelEntry channel;
2285   SilcUInt32 umode = 0;
2286   bool created = FALSE, create_key = TRUE;
2287   SilcClientID *client_id;
2288
2289   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2290
2291   /* Get channel name */
2292   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2293   if (!tmp) {
2294     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2295                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2296                                           0);
2297     goto out;
2298   }
2299   channel_name = tmp;
2300
2301   if (tmp_len > 256)
2302     channel_name[255] = '\0';
2303
2304   if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
2305     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2306                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
2307     goto out;
2308   }
2309
2310   /* Get Client ID of the client who is joining to the channel */
2311   tmp = silc_argument_get_arg_type(cmd->args, 2, &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   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2319   if (!client_id) {
2320     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2321                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2322                                           0);
2323     goto out;
2324   }
2325
2326   /* Get cipher, hmac name and auth payload */
2327   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2328   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2329   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2330   cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2331
2332   /* See if the channel exists */
2333   channel = silc_idlist_find_channel_by_name(server->local_list,
2334                                              channel_name, NULL);
2335
2336   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2337     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2338     if (!entry) {
2339       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2340                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2341                                             0);
2342       goto out;
2343     }
2344
2345     silc_free(client_id);
2346     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2347
2348     if (!channel ||
2349         (channel->disabled && server->server_type != SILC_ROUTER)) {
2350       /* Channel not found or not valid */
2351
2352       /* If we are standalone server we don't have a router, we just create
2353          the channel by ourselves (unless it existed). */
2354       if (server->standalone) {
2355         if (!channel) {
2356           channel = silc_server_create_new_channel(server, server->id, cipher,
2357                                                    hmac, channel_name, TRUE);
2358           if (!channel) {
2359             silc_server_command_send_status_data(
2360                                   cmd, SILC_COMMAND_JOIN,
2361                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2362                                   0, 2, cipher, strlen(cipher));
2363             silc_free(client_id);
2364             goto out;
2365           }
2366
2367           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2368           created = TRUE;
2369           create_key = FALSE;
2370         }
2371       } else {
2372
2373         /* The channel does not exist on our server. If we are normal server
2374            we will send JOIN command to our router which will handle the
2375            joining procedure (either creates the channel if it doesn't exist
2376            or joins the client to it). */
2377         if (server->server_type != SILC_ROUTER) {
2378           SilcBuffer tmpbuf;
2379           SilcUInt16 old_ident;
2380
2381           /* If this is pending command callback then we've resolved
2382              it and it didn't work, return since we've notified the
2383              client already in the command reply callback. */
2384           if (cmd->pending) {
2385             silc_free(client_id);
2386             goto out;
2387           }
2388
2389           old_ident = silc_command_get_ident(cmd->payload);
2390           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2391           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2392
2393           /* Send JOIN command to our router */
2394           silc_server_packet_send(server, (SilcSocketConnection)
2395                                   SILC_PRIMARY_ROUTE(server),
2396                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2397                                   tmpbuf->data, tmpbuf->len, TRUE);
2398
2399           /* Reprocess this packet after received reply from router */
2400           silc_server_command_pending(server, SILC_COMMAND_JOIN,
2401                                       silc_command_get_ident(cmd->payload),
2402                                       silc_server_command_join,
2403                                       silc_server_command_dup(cmd));
2404           cmd->pending = TRUE;
2405           silc_command_set_ident(cmd->payload, old_ident);
2406           silc_buffer_free(tmpbuf);
2407           silc_free(client_id);
2408           goto out;
2409         }
2410
2411         /* We are router and the channel does not seem exist so we will check
2412            our global list as well for the channel. */
2413         channel = silc_idlist_find_channel_by_name(server->global_list,
2414                                                    channel_name, NULL);
2415         if (!channel) {
2416           /* Channel really does not exist, create it */
2417           channel = silc_server_create_new_channel(server, server->id, cipher,
2418                                                    hmac, channel_name, TRUE);
2419           if (!channel) {
2420             silc_server_command_send_status_data(
2421                                        cmd, SILC_COMMAND_JOIN,
2422                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2423                                        2, cipher, strlen(cipher));
2424             silc_free(client_id);
2425             goto out;
2426           }
2427
2428           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2429           created = TRUE;
2430           create_key = FALSE;
2431         }
2432       }
2433     }
2434   } else {
2435     if (!channel) {
2436       /* Channel not found */
2437
2438       /* If the command came from router and we are normal server then
2439          something went wrong with the joining as the channel was not found.
2440          We can't do anything else but ignore this. */
2441       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2442           server->server_type != SILC_ROUTER) {
2443         silc_free(client_id);
2444         goto out;
2445       }
2446
2447       /* We are router and the channel does not seem exist so we will check
2448          our global list as well for the channel. */
2449       channel = silc_idlist_find_channel_by_name(server->global_list,
2450                                                  channel_name, NULL);
2451       if (!channel) {
2452         /* Channel really does not exist, create it */
2453         channel = silc_server_create_new_channel(server, server->id, cipher,
2454                                                  hmac, channel_name, TRUE);
2455         if (!channel) {
2456           silc_server_command_send_status_data(
2457                                        cmd, SILC_COMMAND_JOIN,
2458                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2459                                        2, cipher, strlen(cipher));
2460           silc_free(client_id);
2461           goto out;
2462         }
2463
2464         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2465         created = TRUE;
2466         create_key = FALSE;
2467       }
2468     }
2469   }
2470
2471   /* Check whether the channel was created by our router */
2472   if (cmd->pending && context2) {
2473     SilcServerCommandReplyContext reply = context2;
2474
2475     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2476       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2477       SILC_GET32_MSB(created, tmp);
2478       if (silc_argument_get_arg_type(reply->args, 7, NULL))
2479         create_key = FALSE;     /* Router returned the key already */
2480
2481       if (silc_command_get_status(reply->payload, NULL, NULL) &&
2482           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2483         /* Save channel passphrase, if user provided it successfully */
2484         unsigned char *pa;
2485         SilcUInt32 pa_len;
2486         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2487         if (pa) {
2488           silc_free(channel->passphrase);
2489           channel->passphrase = silc_memdup(pa, pa_len);
2490         }
2491       }
2492     }
2493
2494     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2495         !channel->disabled && !silc_hash_table_count(channel->user_list))
2496       created = TRUE;
2497   }
2498
2499   /* If the channel does not have global users and is also empty the client
2500      will be the channel founder and operator. */
2501   if (!channel->disabled &&
2502       !channel->global_users && !silc_hash_table_count(channel->user_list))
2503     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2504
2505   /* Join to the channel */
2506   silc_server_command_join_channel(server, cmd, channel, client_id,
2507                                    created, create_key, umode,
2508                                    auth, auth_len, cauth, cauth_len);
2509
2510   silc_free(client_id);
2511
2512  out:
2513   silc_server_command_free(cmd);
2514 }
2515
2516 /* Server side of command MOTD. Sends server's current "message of the
2517    day" to the client. */
2518
2519 SILC_SERVER_CMD_FUNC(motd)
2520 {
2521   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2522   SilcServer server = cmd->server;
2523   SilcBuffer packet, idp;
2524   char *motd, *dest_server;
2525   SilcUInt32 motd_len;
2526   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2527
2528   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2529
2530   /* Get server name */
2531   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2532   if (!dest_server) {
2533     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2534                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2535                                           0);
2536     goto out;
2537   }
2538
2539   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2540     /* Send our MOTD */
2541
2542     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2543
2544     if (server->config && server->config->server_info &&
2545         server->config->server_info->motd_file) {
2546       /* Send motd */
2547       motd = silc_file_readfile(server->config->server_info->motd_file,
2548                                 &motd_len);
2549       if (!motd)
2550         goto out;
2551
2552       motd[motd_len] = 0;
2553       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2554                                                     SILC_STATUS_OK, 0,
2555                                                     ident, 2,
2556                                                     2, idp, idp->len,
2557                                                     3, motd, motd_len);
2558     } else {
2559       /* No motd */
2560       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2561                                                     SILC_STATUS_OK, 0,
2562                                                     ident, 1,
2563                                                     2, idp, idp->len);
2564     }
2565
2566     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2567                             packet->data, packet->len, FALSE);
2568     silc_buffer_free(packet);
2569     silc_buffer_free(idp);
2570   } else {
2571     SilcServerEntry entry;
2572
2573     /* Check whether we have this server cached */
2574     entry = silc_idlist_find_server_by_name(server->global_list,
2575                                             dest_server, TRUE, NULL);
2576     if (!entry) {
2577       entry = silc_idlist_find_server_by_name(server->local_list,
2578                                               dest_server, TRUE, NULL);
2579     }
2580
2581     if (server->server_type != SILC_SERVER && !cmd->pending &&
2582         entry && !entry->motd) {
2583       /* Send to the server */
2584       SilcBuffer tmpbuf;
2585       SilcUInt16 old_ident;
2586
2587       old_ident = silc_command_get_ident(cmd->payload);
2588       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2589       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2590
2591       silc_server_packet_send(server, entry->connection,
2592                               SILC_PACKET_COMMAND, cmd->packet->flags,
2593                               tmpbuf->data, tmpbuf->len, TRUE);
2594
2595       /* Reprocess this packet after received reply from router */
2596       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2597                                   silc_command_get_ident(cmd->payload),
2598                                   silc_server_command_motd,
2599                                   silc_server_command_dup(cmd));
2600       cmd->pending = TRUE;
2601       silc_command_set_ident(cmd->payload, old_ident);
2602       silc_buffer_free(tmpbuf);
2603       goto out;
2604     }
2605
2606     if (!entry && !cmd->pending && !server->standalone) {
2607       /* Send to the primary router */
2608       SilcBuffer tmpbuf;
2609       SilcUInt16 old_ident;
2610
2611       old_ident = silc_command_get_ident(cmd->payload);
2612       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2613       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2614
2615       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2616                               SILC_PACKET_COMMAND, cmd->packet->flags,
2617                               tmpbuf->data, tmpbuf->len, TRUE);
2618
2619       /* Reprocess this packet after received reply from router */
2620       silc_server_command_pending(server, SILC_COMMAND_MOTD,
2621                                   silc_command_get_ident(cmd->payload),
2622                                   silc_server_command_motd,
2623                                   silc_server_command_dup(cmd));
2624       cmd->pending = TRUE;
2625       silc_command_set_ident(cmd->payload, old_ident);
2626       silc_buffer_free(tmpbuf);
2627       goto out;
2628     }
2629
2630     if (!entry) {
2631       silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2632                                            SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2633                                            2, dest_server,
2634                                            strlen(dest_server));
2635       goto out;
2636     }
2637
2638     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2639     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2640                                                   SILC_STATUS_OK, 0, ident, 2,
2641                                                   2, idp, idp->len,
2642                                                   3, entry->motd,
2643                                                   entry->motd ?
2644                                                   strlen(entry->motd) : 0);
2645     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2646                             packet->data, packet->len, FALSE);
2647     silc_buffer_free(packet);
2648     silc_buffer_free(idp);
2649   }
2650
2651  out:
2652   silc_server_command_free(cmd);
2653 }
2654
2655 /* Server side of command UMODE. Client can use this command to set/unset
2656    user mode. Client actually cannot set itself to be as server/router
2657    operator so this can be used only to unset the modes. */
2658
2659 SILC_SERVER_CMD_FUNC(umode)
2660 {
2661   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2662   SilcServer server = cmd->server;
2663   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2664   SilcBuffer packet;
2665   unsigned char *tmp_mask, m[4];
2666   SilcUInt32 mask = 0;
2667   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2668   bool set_mask = FALSE;
2669
2670   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2671     goto out;
2672
2673   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2674
2675   /* Get the client's mode mask */
2676   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2677   if (tmp_mask) {
2678     SILC_GET32_MSB(mask, tmp_mask);
2679     set_mask = TRUE;
2680   }
2681
2682   if (set_mask) {
2683     /* Check that mode changing is allowed. */
2684     if (!silc_server_check_umode_rights(server, client, mask)) {
2685       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2686                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2687       goto out;
2688     }
2689
2690     /* Anonymous mode cannot be set by client */
2691     if (mask & SILC_UMODE_ANONYMOUS) {
2692       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2693         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2694                                               SILC_STATUS_ERR_PERM_DENIED, 0);
2695         goto out;
2696       }
2697     } else {
2698       if (client->mode & SILC_UMODE_ANONYMOUS) {
2699         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2700                                               SILC_STATUS_ERR_PERM_DENIED, 0);
2701         goto out;
2702       }
2703     }
2704
2705     /* Update statistics */
2706     if (mask & SILC_UMODE_GONE) {
2707       if (!(client->mode & SILC_UMODE_GONE))
2708         server->stat.my_aways++;
2709     } else {
2710       if (client->mode & SILC_UMODE_GONE)
2711         server->stat.my_aways--;
2712     }
2713
2714     /* Change the mode */
2715     client->mode = mask;
2716
2717     /* Send UMODE change to primary router */
2718     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2719                                   SILC_BROADCAST(server), client->id,
2720                                   client->mode);
2721
2722     /* Check if anyone is watching this nickname */
2723     if (server->server_type == SILC_ROUTER)
2724       silc_server_check_watcher_list(server, client, NULL,
2725                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
2726   }
2727
2728   /* Send command reply to sender */
2729   SILC_PUT32_MSB(client->mode, m);
2730   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2731                                                 SILC_STATUS_OK, 0, ident, 1,
2732                                                 2, m, sizeof(m));
2733   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2734                           packet->data, packet->len, FALSE);
2735   silc_buffer_free(packet);
2736
2737  out:
2738   silc_server_command_free(cmd);
2739 }
2740
2741 /* Server side command of CMODE. Changes channel mode */
2742
2743 SILC_SERVER_CMD_FUNC(cmode)
2744 {
2745   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2746   SilcServer server = cmd->server;
2747   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2748   SilcIDListData idata = (SilcIDListData)client;
2749   SilcChannelID *channel_id = NULL;
2750   SilcChannelEntry channel;
2751   SilcChannelClientEntry chl;
2752   SilcBuffer packet, cidp;
2753   unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2754   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2755   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2756   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2757   bool set_mask = FALSE, set_chpk = FALSE;
2758   SilcPublicKey founder_key = NULL;
2759   SilcBuffer fkey = NULL, chpklist = NULL;
2760   SilcBufferStruct chpk;
2761
2762   if (!client) {
2763     silc_server_command_free(cmd);
2764     return;
2765   }
2766
2767   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2768
2769   /* Get Channel ID */
2770   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2771   if (!tmp_id) {
2772     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2773                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2774     silc_server_command_free(cmd);
2775     return;
2776   }
2777   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2778   if (!channel_id) {
2779     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2780                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2781     silc_server_command_free(cmd);
2782     return;
2783   }
2784
2785   /* Get channel entry */
2786   channel = silc_idlist_find_channel_by_id(server->local_list,
2787                                            channel_id, NULL);
2788   if (!channel) {
2789     channel = silc_idlist_find_channel_by_id(server->global_list,
2790                                              channel_id, NULL);
2791     if (!channel) {
2792       silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2793                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2794                                            0, 2, tmp_id, tmp_len2);
2795       silc_free(channel_id);
2796       silc_server_command_free(cmd);
2797       return;
2798     }
2799   }
2800   old_mask = channel->mode;
2801
2802   /* Get the channel mode mask */
2803   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2804   if (tmp_mask) {
2805     SILC_GET32_MSB(mode_mask, tmp_mask);
2806     set_mask = TRUE;
2807   }
2808
2809   /* Check whether this client is on the channel */
2810   if (!silc_server_client_on_channel(client, channel, &chl)) {
2811     silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2812                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2813                                          2, tmp_id, tmp_len2);
2814     goto out;
2815   }
2816
2817   /* Check that client has rights to change any requested channel modes */
2818   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2819                                                   mode_mask)) {
2820     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2821     silc_server_command_send_status_data(
2822                              cmd, SILC_COMMAND_CMODE,
2823                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2824                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2825                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2826                              2, tmp_id, tmp_len2);
2827     goto out;
2828   }
2829
2830   /* If mode mask was not sent as argument then merely return the current
2831      mode mask, founder key and channel public key list to the sender. */
2832   if (!set_mask) {
2833     unsigned char m[4];
2834     SILC_PUT32_MSB(channel->mode, m);
2835     if (channel->founder_key)
2836       fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2837     if (channel->channel_pubkeys)
2838       chpklist = silc_server_get_channel_pk_list(server, channel,
2839                                                  FALSE, FALSE);
2840     packet =
2841       silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2842                                            SILC_STATUS_OK, 0, ident, 4,
2843                                            2, tmp_id, tmp_len2,
2844                                            3, m, sizeof(m),
2845                                            4, fkey ? fkey->data : NULL,
2846                                            fkey ? fkey->len : 0,
2847                                            5, chpklist ? chpklist->data : NULL,
2848                                            chpklist ? chpklist->len : 0);
2849     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2850                             packet->data, packet->len, FALSE);
2851     silc_buffer_free(packet);
2852     goto out;
2853   }
2854
2855   /*
2856    * Check the modes. Modes that requires nothing special operation are
2857    * not checked here.
2858    */
2859
2860   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2861     /* Channel uses private keys to protect traffic. Client(s) has set the
2862        key locally they want to use, server does not know that key. */
2863     /* Nothing interesting to do here */
2864   } else {
2865     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2866       /* The mode is removed and we need to generate and distribute
2867          new channel key. Clients are not using private channel keys
2868          anymore after this. */
2869
2870       /* Re-generate channel key */
2871       if (!silc_server_create_channel_key(server, channel, 0))
2872         goto out;
2873
2874       /* Send the channel key. This sends it to our local clients and if
2875          we are normal server to our router as well. */
2876       silc_server_send_channel_key(server, NULL, channel,
2877                                    server->server_type == SILC_ROUTER ?
2878                                    FALSE : !server->standalone);
2879
2880       cipher = (char *)silc_cipher_get_name(channel->channel_key);
2881       hmac = (char *)silc_hmac_get_name(channel->hmac);
2882     }
2883   }
2884
2885   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2886     /* User limit is set on channel */
2887     SilcUInt32 user_limit;
2888
2889     /* Get user limit */
2890     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2891     if (!tmp) {
2892       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2893         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2894                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2895         goto out;
2896       }
2897     } else {
2898       SILC_GET32_MSB(user_limit, tmp);
2899       channel->user_limit = user_limit;
2900     }
2901   } else {
2902     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2903       /* User limit mode is unset. Remove user limit */
2904       channel->user_limit = 0;
2905   }
2906
2907   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2908     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2909       /* Passphrase has been set to channel */
2910
2911       /* Get the passphrase */
2912       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2913       if (!tmp) {
2914         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2915                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2916         goto out;
2917       }
2918
2919       /* Save the passphrase */
2920       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2921     }
2922   } else {
2923     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2924       /* Passphrase mode is unset. remove the passphrase */
2925       silc_free(channel->passphrase);
2926       channel->passphrase = NULL;
2927     }
2928   }
2929
2930   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2931     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2932       /* Cipher to use protect the traffic */
2933       SilcCipher newkey, oldkey;
2934
2935       /* Get cipher */
2936       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2937       if (!cipher) {
2938         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2939                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2940         goto out;
2941       }
2942
2943       /* Delete old cipher and allocate the new one */
2944       if (!silc_cipher_alloc(cipher, &newkey)) {
2945         silc_server_command_send_status_data(
2946                                          cmd, SILC_COMMAND_CMODE,
2947                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2948                                          2, cipher, strlen(cipher));
2949         goto out;
2950       }
2951
2952       oldkey = channel->channel_key;
2953       channel->channel_key = newkey;
2954
2955       /* Re-generate channel key */
2956       if (!silc_server_create_channel_key(server, channel, 0)) {
2957         /* We don't have new key, revert to old one */
2958         channel->channel_key = oldkey;
2959         goto out;
2960       }
2961
2962       /* Remove old channel key for good */
2963       silc_cipher_free(oldkey);
2964
2965       /* Send the channel key. This sends it to our local clients and if
2966          we are normal server to our router as well. */
2967       silc_server_send_channel_key(server, NULL, channel,
2968                                    server->server_type == SILC_ROUTER ?
2969                                    FALSE : !server->standalone);
2970     }
2971   } else {
2972     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2973       /* Cipher mode is unset. Remove the cipher and revert back to
2974          default cipher */
2975       SilcCipher newkey, oldkey;
2976       cipher = channel->cipher;
2977
2978       /* Delete old cipher and allocate default one */
2979       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2980         silc_server_command_send_status_data(
2981                                       cmd, SILC_COMMAND_CMODE,
2982                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2983                                       2, cipher, strlen(cipher));
2984         goto out;
2985       }
2986
2987       oldkey = channel->channel_key;
2988       channel->channel_key = newkey;
2989
2990       /* Re-generate channel key */
2991       if (!silc_server_create_channel_key(server, channel, 0)) {
2992         /* We don't have new key, revert to old one */
2993         channel->channel_key = oldkey;
2994         goto out;
2995       }
2996
2997       /* Remove old channel key for good */
2998       silc_cipher_free(oldkey);
2999
3000       /* Send the channel key. This sends it to our local clients and if
3001          we are normal server to our router as well. */
3002       silc_server_send_channel_key(server, NULL, channel,
3003                                    server->server_type == SILC_ROUTER ?
3004                                    FALSE : !server->standalone);
3005     }
3006   }
3007
3008   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3009     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3010       /* HMAC to use protect the traffic */
3011       unsigned char hash[32];
3012       SilcHmac newhmac;
3013
3014       /* Get hmac */
3015       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3016       if (!hmac) {
3017         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3018                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3019         goto out;
3020       }
3021
3022       /* Delete old hmac and allocate the new one */
3023       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3024         silc_server_command_send_status_data(
3025                                         cmd, SILC_COMMAND_CMODE,
3026                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3027                                         2, hmac, strlen(hmac));
3028         goto out;
3029       }
3030
3031       silc_hmac_free(channel->hmac);
3032       channel->hmac = newhmac;
3033
3034       /* Set the HMAC key out of current channel key. The client must do
3035          this locally. */
3036       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3037                      channel->key_len / 8, hash);
3038       silc_hmac_set_key(channel->hmac, hash,
3039                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3040       memset(hash, 0, sizeof(hash));
3041     }
3042   } else {
3043     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3044       /* Hmac mode is unset. Remove the hmac and revert back to
3045          default hmac */
3046       SilcHmac newhmac;
3047       unsigned char hash[32];
3048       hmac = channel->hmac_name;
3049
3050       /* Delete old hmac and allocate default one */
3051       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3052         silc_server_command_send_status_data(
3053                                         cmd, SILC_COMMAND_CMODE,
3054                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3055                                         2, hmac, strlen(hmac));
3056         goto out;
3057       }
3058
3059       silc_hmac_free(channel->hmac);
3060       channel->hmac = newhmac;
3061
3062       /* Set the HMAC key out of current channel key. The client must do
3063          this locally. */
3064       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3065                      channel->key_len / 8,
3066                      hash);
3067       silc_hmac_set_key(channel->hmac, hash,
3068                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3069       memset(hash, 0, sizeof(hash));
3070     }
3071   }
3072
3073   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3074     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3075       /* Check if the founder public key was received */
3076       founder_key = idata->public_key;
3077       tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3078       if (tmp) {
3079         if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3080           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3081                                                 SILC_STATUS_ERR_AUTH_FAILED,
3082                                                 0);
3083           goto out;
3084         }
3085       } else {
3086         /* If key was not sent and the channel mode has already founder
3087            then the key was not to be changed. */
3088         if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3089           goto has_founder;
3090       }
3091
3092       /* Set the founder authentication */
3093       tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3094       if (!tmp) {
3095         silc_server_command_send_status_reply(
3096                                      cmd, SILC_COMMAND_CMODE,
3097                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3098         goto out;
3099       }
3100
3101       /* Verify the payload before setting the mode */
3102       if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3103                                  founder_key, 0, server->sha1hash,
3104                                  client->id, SILC_ID_CLIENT)) {
3105         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3106                                               SILC_STATUS_ERR_AUTH_FAILED,
3107                                               0);
3108         goto out;
3109       }
3110
3111       /* Save the public key */
3112       if (channel->founder_key)
3113         silc_pkcs_public_key_free(channel->founder_key);
3114       if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3115         channel->founder_key = founder_key;
3116       else
3117         channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3118       if (!channel->founder_key) {
3119         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3120                                               SILC_STATUS_ERR_AUTH_FAILED,
3121                                               0);
3122         goto out;
3123       }
3124
3125       fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3126       if (!fkey) {
3127         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3128                                               SILC_STATUS_ERR_AUTH_FAILED,
3129                                               0);
3130         silc_pkcs_public_key_free(channel->founder_key);
3131         channel->founder_key = NULL;
3132         goto out;
3133       }
3134     has_founder:
3135     }
3136   } else {
3137     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3138       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3139         if (channel->founder_key)
3140           silc_pkcs_public_key_free(channel->founder_key);
3141         channel->founder_key = NULL;
3142       }
3143     }
3144   }
3145
3146   if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3147     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3148       SilcStatus st;
3149
3150       chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3151
3152       if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3153         goto has_pk_list;
3154
3155       set_chpk = TRUE;
3156
3157       /* Process the channel public key(s) */
3158       st = silc_server_set_channel_pk_list(server, NULL, channel,
3159                                            chpkdata, chpklen);
3160       if (st != SILC_STATUS_OK) {
3161         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3162         goto out;
3163       }
3164     has_pk_list:
3165     }
3166   } else {
3167     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3168       if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3169         if (channel->channel_pubkeys)
3170           silc_hash_table_free(channel->channel_pubkeys);
3171         channel->channel_pubkeys = NULL;
3172         set_chpk = TRUE;
3173       }
3174     }
3175   }
3176
3177   /* Finally, set the mode */
3178   old_mask = channel->mode = mode_mask;
3179
3180   /* Send CMODE_CHANGE notify. */
3181   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3182   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3183                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
3184                                      cidp->data, cidp->len,
3185                                      tmp_mask, 4,
3186                                      cipher, cipher ? strlen(cipher) : 0,
3187                                      hmac, hmac ? strlen(hmac) : 0,
3188                                      passphrase, passphrase ?
3189                                      strlen(passphrase) : 0,
3190                                      fkey ? fkey->data : NULL,
3191                                      fkey ? fkey->len : 0,
3192                                      chpkdata ? chpkdata : NULL,
3193                                      chpkdata ? chpklen : 0);
3194
3195   /* Set CMODE notify type to network */
3196   if (chpkdata && chpklen)
3197     silc_buffer_set(&chpk, chpkdata, chpklen);
3198   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3199                                 SILC_BROADCAST(server), channel,
3200                                 mode_mask, client->id, SILC_ID_CLIENT,
3201                                 cipher, hmac, passphrase, founder_key,
3202                                 chpkdata ? &chpk : NULL);
3203
3204   if (set_chpk)
3205     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3206
3207   /* Send command reply to sender */
3208   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3209                                                 SILC_STATUS_OK, 0, ident, 4,
3210                                                 2, tmp_id, tmp_len2,
3211                                                 3, tmp_mask, 4,
3212                                                 4, fkey ? fkey->data : NULL,
3213                                                 fkey ? fkey->len : 0,
3214                                                 5, chpklist ? chpklist->data :
3215                                                 NULL, chpklist ? chpklist->len
3216                                                 : 0);
3217   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3218                           packet->data, packet->len, FALSE);
3219
3220   silc_buffer_free(packet);
3221   silc_buffer_free(cidp);
3222
3223  out:
3224   channel->mode = old_mask;
3225   silc_buffer_free(chpklist);
3226   silc_buffer_free(fkey);
3227   silc_free(channel_id);
3228   silc_server_command_free(cmd);
3229 }
3230
3231 /* Server side of CUMODE command. Changes client's mode on a channel. */
3232
3233 SILC_SERVER_CMD_FUNC(cumode)
3234 {
3235   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3236   SilcServer server = cmd->server;
3237   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3238   SilcChannelID *channel_id = NULL;
3239   SilcClientID *client_id = NULL;
3240   SilcChannelEntry channel;
3241   SilcClientEntry target_client;
3242   SilcChannelClientEntry chl;
3243   SilcBuffer packet, idp;
3244   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3245   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3246   int notify = FALSE;
3247   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3248   SilcPublicKey founder_key = NULL;
3249   SilcBuffer fkey = NULL;
3250
3251   if (!client)
3252     goto out;
3253
3254   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3255
3256   /* Get Channel ID */
3257   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3258   if (!tmp_ch_id) {
3259     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3260                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3261     goto out;
3262   }
3263   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3264   if (!channel_id) {
3265     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3266                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3267     goto out;
3268   }
3269
3270   /* Get channel entry */
3271   channel = silc_idlist_find_channel_by_id(server->local_list,
3272                                            channel_id, NULL);
3273   if (!channel) {
3274     channel = silc_idlist_find_channel_by_id(server->global_list,
3275                                              channel_id, NULL);
3276     if (!channel) {
3277       silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3278                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3279                                            0, 2, tmp_ch_id, tmp_ch_len);
3280       goto out;
3281     }
3282   }
3283
3284   /* Check whether sender is on the channel */
3285   if (!silc_server_client_on_channel(client, channel, &chl)) {
3286     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3287                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3288                                          2, tmp_ch_id, tmp_ch_len);
3289     goto out;
3290   }
3291   sender_mask = chl->mode;
3292
3293   /* Get the target client's channel mode mask */
3294   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3295   if (!tmp_mask) {
3296     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3297                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3298                                           0);
3299     goto out;
3300   }
3301   SILC_GET32_MSB(target_mask, tmp_mask);
3302
3303   /* Get target Client ID */
3304   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3305   if (!tmp_id) {
3306     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3307                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3308     goto out;
3309   }
3310   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3311   if (!client_id) {
3312     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3313                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3314     goto out;
3315   }
3316
3317   /* Get target client's entry */
3318   target_client = silc_idlist_find_client_by_id(server->local_list,
3319                                                 client_id, TRUE, NULL);
3320   if (!target_client) {
3321     target_client = silc_idlist_find_client_by_id(server->global_list,
3322                                                   client_id, TRUE, NULL);
3323   }
3324
3325   if (target_client != client &&
3326       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3327       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3328     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3329                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
3330                                          2, tmp_ch_id, tmp_ch_len);
3331     goto out;
3332   }
3333
3334   /* Check whether target client is on the channel */
3335   if (target_client != client) {
3336     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3337       silc_server_command_send_status_data2(
3338                                   cmd, SILC_COMMAND_CUMODE,
3339                                   SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3340                                   2, tmp_id, tmp_len,
3341                                   3, tmp_ch_id, tmp_ch_len);
3342       goto out;
3343     }
3344   }
3345
3346   /*
3347    * Change the mode
3348    */
3349
3350   /* If the target client is founder, no one else can change their mode
3351      but themselves. */
3352   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3353     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3354                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3355                                          0, 2, tmp_ch_id, tmp_ch_len);
3356     goto out;
3357   }
3358
3359   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3360     if (target_client != client) {
3361       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3362                                             SILC_STATUS_ERR_NOT_YOU, 0);
3363       goto out;
3364     }
3365
3366     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3367       /* The client tries to claim the founder rights. */
3368       unsigned char *tmp_auth;
3369       SilcUInt32 tmp_auth_len;
3370       SilcChannelClientEntry chl2;
3371       SilcHashTableList htl;
3372
3373       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3374           !channel->founder_key) {
3375         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3376                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3377         goto out;
3378       }
3379
3380       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3381       if (!tmp_auth) {
3382         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3383                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3384         goto out;
3385       }
3386
3387       /* Verify the authentication payload */
3388       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3389                                  channel->founder_key, 0, server->sha1hash,
3390                                  client->id, SILC_ID_CLIENT)) {
3391         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3392                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3393         goto out;
3394       }
3395
3396       notify = TRUE;
3397       founder_key = channel->founder_key;
3398       fkey = silc_pkcs_public_key_payload_encode(founder_key);
3399       if (!fkey) {
3400         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3401                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3402         goto out;
3403       }
3404
3405       /* There cannot be anyone else as founder on the channel now.  This
3406          client is definitely the founder due to this authentication */
3407       silc_hash_table_list(channel->user_list, &htl);
3408       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3409         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3410           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3411           silc_server_force_cumode_change(server, NULL, channel, chl2,
3412                                           chl2->mode);
3413           break;
3414         }
3415       silc_hash_table_list_reset(&htl);
3416
3417       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3418     }
3419   } else {
3420     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3421       if (target_client == client) {
3422         /* Remove channel founder rights from itself */
3423         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3424         notify = TRUE;
3425       } else {
3426         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3427                                               SILC_STATUS_ERR_NOT_YOU, 0);
3428         goto out;
3429       }
3430     }
3431   }
3432
3433   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3434     /* Promote to operator */
3435     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3436       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3437           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3438         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3439                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3440                                              0, 2, tmp_ch_id, tmp_ch_len);
3441         goto out;
3442       }
3443
3444       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3445       notify = TRUE;
3446     }
3447   } else {
3448     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3449       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3450           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3451         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3452                                              SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3453                                              0, 2, tmp_ch_id, tmp_ch_len);
3454         goto out;
3455       }
3456
3457       /* Demote to normal user */
3458       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3459       notify = TRUE;
3460     }
3461   }
3462
3463   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3464     if (target_client != client) {
3465       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3466                                             SILC_STATUS_ERR_NOT_YOU, 0);
3467       goto out;
3468     }
3469
3470     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3471       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3472       notify = TRUE;
3473     }
3474   } else {
3475     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3476       if (target_client != client) {
3477         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3478                                               SILC_STATUS_ERR_NOT_YOU, 0);
3479         goto out;
3480       }
3481
3482       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3483       notify = TRUE;
3484     }
3485   }
3486
3487   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3488     if (target_client != client) {
3489       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3490                                             SILC_STATUS_ERR_NOT_YOU, 0);
3491       goto out;
3492     }
3493
3494     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3495       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3496       notify = TRUE;
3497     }
3498   } else {
3499     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3500       if (target_client != client) {
3501         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3502                                               SILC_STATUS_ERR_NOT_YOU, 0);
3503         goto out;
3504       }
3505
3506       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3507       notify = TRUE;
3508     }
3509   }
3510
3511   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3512     if (target_client != client) {
3513       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3514                                             SILC_STATUS_ERR_NOT_YOU, 0);
3515       goto out;
3516     }
3517
3518     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3519       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3520       notify = TRUE;
3521     }
3522   } else {
3523     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3524       if (target_client != client) {
3525         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3526                                               SILC_STATUS_ERR_NOT_YOU, 0);
3527         goto out;
3528       }
3529
3530       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3531       notify = TRUE;
3532     }
3533   }
3534
3535   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3536     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3537       if (client == target_client) {
3538         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3539                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3540         goto out;
3541       }
3542       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3543       notify = TRUE;
3544     }
3545   } else {
3546     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3547       if (client == target_client) {
3548         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3549                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3550         goto out;
3551       }
3552       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3553       notify = TRUE;
3554     }
3555   }
3556
3557   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3558   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3559
3560   /* Send notify to channel, notify only if mode was actually changed. */
3561   if (notify) {
3562     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3563                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3564                                        idp->data, idp->len,
3565                                        tmp_mask, 4,
3566                                        tmp_id, tmp_len,
3567                                        fkey ? fkey->data : NULL,
3568                                        fkey ? fkey->len : 0);
3569
3570     /* Set CUMODE notify type to network */
3571     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3572                                    SILC_BROADCAST(server), channel,
3573                                    target_mask, client->id, SILC_ID_CLIENT,
3574                                    target_client->id, founder_key);
3575   }
3576
3577   /* Send command reply to sender */
3578   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3579                                                 SILC_STATUS_OK, 0, ident, 3,
3580                                                 2, tmp_mask, 4,
3581                                                 3, tmp_ch_id, tmp_ch_len,
3582                                                 4, tmp_id, tmp_len);
3583   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3584                           packet->data, packet->len, FALSE);
3585
3586   silc_buffer_free(packet);
3587   silc_buffer_free(idp);
3588
3589  out:
3590   silc_free(channel_id);
3591   silc_free(client_id);
3592   silc_buffer_free(fkey);
3593   silc_server_command_free(cmd);
3594 }
3595
3596 /* Server side of KICK command. Kicks client out of channel. */
3597
3598 SILC_SERVER_CMD_FUNC(kick)
3599 {
3600   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601   SilcServer server = cmd->server;
3602   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3603   SilcClientEntry target_client;
3604   SilcChannelID *channel_id;
3605   SilcClientID *client_id;
3606   SilcChannelEntry channel;
3607   SilcChannelClientEntry chl;
3608   SilcBuffer idp, packet;
3609   SilcUInt32 tmp_len, target_idp_len, clen;
3610   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3611   unsigned char *tmp, *comment, *target_idp;
3612
3613   if (!client)
3614     goto out;
3615
3616   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3617
3618   /* Get Channel ID */
3619   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3620   if (!tmp) {
3621     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3622                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3623     goto out;
3624   }
3625   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3626   if (!channel_id) {
3627     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3628                                          SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
3629                                          2, tmp, tmp_len);
3630     goto out;
3631   }
3632
3633   /* Get channel entry */
3634   channel = silc_idlist_find_channel_by_id(server->local_list,
3635                                            channel_id, NULL);
3636   if (!channel) {
3637     channel = silc_idlist_find_channel_by_id(server->local_list,
3638                                              channel_id, NULL);
3639     if (!channel) {
3640       silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3641                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3642                                            0, 2, tmp, tmp_len);
3643       goto out;
3644     }
3645   }
3646
3647   /* Check whether sender is on the channel */
3648   if (!silc_server_client_on_channel(client, channel, &chl)) {
3649     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3650                                          SILC_STATUS_ERR_NOT_ON_CHANNEL,
3651                                          0, 2, tmp, tmp_len);
3652     goto out;
3653   }
3654
3655   /* Check that the kicker is channel operator or channel founder */
3656   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3657       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3658     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3659                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3660                                          0, 2, tmp, tmp_len);
3661     goto out;
3662   }
3663
3664   /* Get target Client ID */
3665   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3666   if (!target_idp) {
3667     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3668                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3669     goto out;
3670   }
3671   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3672   if (!client_id) {
3673     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3674                                          SILC_STATUS_ERR_BAD_CLIENT_ID,
3675                                          0, 2, target_idp, target_idp_len);
3676     goto out;
3677   }
3678
3679   /* Get target client's entry */
3680   target_client = silc_idlist_find_client_by_id(server->local_list,
3681                                                 client_id, TRUE, NULL);
3682   if (!target_client) {
3683     target_client = silc_idlist_find_client_by_id(server->global_list,
3684                                                   client_id, TRUE, NULL);
3685   }
3686
3687   /* Check whether target client is on the channel */
3688   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3689     silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3690                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3691                                           0, 2, target_idp, target_idp_len,
3692                                           3, tmp, tmp_len);
3693     goto out;
3694   }
3695
3696   /* Check that the target client is not channel founder. Channel founder
3697      cannot be kicked from the channel. */
3698   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3699     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3700                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3701                                          0, 2, tmp, tmp_len);
3702     goto out;
3703   }
3704
3705   /* Get comment */
3706   comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3707   if (clen > 128)
3708     comment = NULL;
3709
3710
3711   /* Send the reply back to the client */
3712   packet =
3713     silc_command_reply_payload_encode_va(SILC_COMMAND_KICK,
3714                                          SILC_STATUS_OK, 0, ident, 2,
3715                                          2, tmp, tmp_len,
3716                                          3, target_idp, target_idp_len);
3717   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3718                           packet->data, packet->len, FALSE);
3719   silc_buffer_free(packet);
3720
3721   /* Send command reply to sender */
3722   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3723                                         SILC_STATUS_OK, 0);
3724
3725   /* Send KICKED notify to local clients on the channel */
3726   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3727   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3728                                      SILC_NOTIFY_TYPE_KICKED, 3,
3729                                      target_idp, target_idp_len,
3730                                      comment, comment ? strlen(comment) : 0,
3731                                      idp->data, idp->len);
3732   silc_buffer_free(idp);
3733
3734   /* Send KICKED notify to primary route */
3735   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3736                                  SILC_BROADCAST(server), channel,
3737                                  target_client->id, client->id, comment);
3738
3739   /* Remove the client from channel's invite list */
3740   if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3741     SilcBuffer ab =
3742       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3743     SilcArgumentPayload args =
3744       silc_argument_payload_parse(ab->data, ab->len, 1);
3745     silc_server_inviteban_process(server, channel->invite_list, 1, args);
3746     silc_buffer_free(ab);
3747     silc_argument_payload_free(args);
3748   }
3749
3750   /* Remove the client from the channel. If the channel does not exist
3751      after removing the client then the client kicked itself off the channel
3752      and we don't have to send anything after that. */
3753   if (!silc_server_remove_from_one_channel(server, NULL, channel,
3754                                            target_client, FALSE))
3755     goto out;
3756
3757   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3758     /* Re-generate channel key */
3759     if (!silc_server_create_channel_key(server, channel, 0))
3760       goto out;
3761
3762     /* Send the channel key to the channel. The key of course is not sent
3763        to the client who was kicked off the channel. */
3764     silc_server_send_channel_key(server, target_client->connection, channel,
3765                                  server->server_type == SILC_ROUTER ?
3766                                  FALSE : !server->standalone);
3767   }
3768
3769  out:
3770   silc_server_command_free(cmd);
3771 }
3772
3773 /* Server side of OPER command. Client uses this comand to obtain server
3774    operator privileges to this server/router. */
3775
3776 SILC_SERVER_CMD_FUNC(oper)
3777 {
3778   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3779   SilcServer server = cmd->server;
3780   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3781   unsigned char *username, *auth;
3782   SilcUInt32 tmp_len;
3783   SilcServerConfigAdmin *admin;
3784   SilcIDListData idata = (SilcIDListData)client;
3785   bool result = FALSE;
3786   SilcPublicKey cached_key;
3787
3788   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3789     goto out;
3790
3791   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3792
3793   /* Get the username */
3794   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3795   if (!username) {
3796     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3797                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3798                                           0);
3799     goto out;
3800   }
3801
3802   /* Get the admin configuration */
3803   admin = silc_server_config_find_admin(server, cmd->sock->ip,
3804                                         username, client->nickname);
3805   if (!admin) {
3806     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3807                                           username, client->nickname);
3808     if (!admin) {
3809       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3810                                             SILC_STATUS_ERR_AUTH_FAILED,
3811                                             0);
3812       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3813                      "nickname '%s' from %s", username,
3814                      client->nickname, cmd->sock->hostname));
3815       goto out;
3816     }
3817   }
3818
3819   /* Get the authentication payload */
3820   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3821   if (!auth) {
3822     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3823                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3824                                           0);
3825     goto out;
3826   }
3827
3828   /* Verify the authentication data. If both passphrase and public key
3829      is set then try both of them. */
3830   if (admin->passphrase)
3831     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3832                                    admin->passphrase, admin->passphrase_len,
3833                                    idata->hash, client->id, SILC_ID_CLIENT);
3834   if (!result && admin->publickeys) {
3835     cached_key = silc_server_get_public_key(server, admin->publickeys);
3836     if (!cached_key)
3837       goto out;
3838     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3839                                    cached_key, 0, idata->hash,
3840                                    client->id, SILC_ID_CLIENT);
3841   }
3842   if (!result) {
3843     /* Authentication failed */
3844     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3845                                           SILC_STATUS_ERR_AUTH_FAILED,
3846                                           0);
3847     goto out;
3848   }
3849
3850   /* Client is now server operator */
3851   client->mode |= SILC_UMODE_SERVER_OPERATOR;
3852
3853   /* Update statistics */
3854   if (SILC_IS_LOCAL(client))
3855     server->stat.my_server_ops++;
3856   if (server->server_type == SILC_ROUTER)
3857     server->stat.server_ops++;
3858
3859   /* Send UMODE change to primary router */
3860   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3861                                 SILC_BROADCAST(server), client->id,
3862                                 client->mode);
3863
3864   /* Check if anyone is watching this nickname */
3865   if (server->server_type == SILC_ROUTER)
3866     silc_server_check_watcher_list(server, client, NULL,
3867                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3868
3869   /* Send reply to the sender */
3870   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3871                                         SILC_STATUS_OK, 0);
3872
3873  out:
3874   silc_server_command_free(cmd);
3875 }
3876
3877 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3878 {
3879   SilcServer server = app_context;
3880   QuitInternal q = (QuitInternal)context;
3881   SilcClientID *client_id = (SilcClientID *)q->sock;
3882   SilcClientEntry client;
3883   SilcSocketConnection sock;
3884
3885   client = silc_idlist_find_client_by_id(server->local_list, client_id,
3886                                          TRUE, NULL);
3887   if (client && client->connection) {
3888     sock = client->connection;
3889
3890     /* If there is pending outgoing data for the client then purge it
3891        to the network before closing connection. */
3892     silc_server_packet_queue_purge(server, sock);
3893
3894     /* Close the connection on our side */
3895     client->router = NULL;
3896     client->connection = NULL;
3897     sock->user_data = NULL;
3898     silc_server_close_connection(server, sock);
3899   }
3900
3901   silc_free(client_id);
3902   silc_free(q);
3903 }
3904
3905 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3906 {
3907   SilcServer server = app_context;
3908   QuitInternal q = (QuitInternal)context;
3909   SilcClientID *client_id = (SilcClientID *)q->sock;
3910   SilcClientEntry client;
3911
3912   client = silc_idlist_find_client_by_id(server->local_list, client_id,
3913                                          TRUE, NULL);
3914   if (client && client->mode & SILC_UMODE_DETACHED) {
3915     SILC_LOG_DEBUG(("Detach timeout"));
3916     silc_server_free_client_data(server, NULL, client, TRUE,
3917                                  "Detach timeout");
3918   }
3919
3920   silc_free(client_id);
3921   silc_free(q);
3922 }
3923
3924 /* Server side of DETACH command.  Detached the client from the network
3925    by closing the connection but preserving the session. */
3926
3927 SILC_SERVER_CMD_FUNC(detach)
3928 {
3929   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3930   SilcServer server = cmd->server;
3931   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3932   QuitInternal q;
3933
3934   if (server->config->detach_disabled) {
3935     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3936                                           SILC_STATUS_ERR_OPERATION_ALLOWED,
3937                                           0);
3938     goto out;
3939   }
3940
3941   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3942     goto out;
3943
3944   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3945
3946   /* Remove operator privileges, since the client may resume in some
3947      other server which to it does not have operator privileges. */
3948   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3949   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3950
3951   /* Send the user mode notify to notify that client is detached */
3952   client->mode |= SILC_UMODE_DETACHED;
3953   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3954   client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3955   client->last_command = 0;
3956   client->fast_command = 0;
3957   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3958                                 SILC_BROADCAST(server), client->id,
3959                                 client->mode);
3960   server->stat.my_detached++;
3961
3962   /* Check if anyone is watching this nickname */
3963   if (server->server_type == SILC_ROUTER)
3964     silc_server_check_watcher_list(server, client, NULL,
3965                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3966
3967   q = silc_calloc(1, sizeof(*q));
3968   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3969   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3970                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3971
3972   if (server->config->detach_timeout) {
3973     q = silc_calloc(1, sizeof(*q));
3974     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3975     silc_schedule_task_add(server->schedule, 0,
3976                            silc_server_command_detach_timeout,
3977                            q, server->config->detach_timeout * 60,
3978                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3979   }
3980
3981   /* Send reply to the sender */
3982   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3983                                         SILC_STATUS_OK, 0);
3984
3985  out:
3986   silc_server_command_free(cmd);
3987 }
3988
3989 /* Server side of WATCH command. */
3990
3991 SILC_SERVER_CMD_FUNC(watch)
3992 {
3993   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3994   SilcServer server = cmd->server;
3995   char *add_nick, *del_nick;
3996   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3997   char nick[128 + 1];
3998   unsigned char hash[16], *tmp;
3999   SilcClientEntry client;
4000   SilcClientID *client_id = NULL;
4001
4002   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4003
4004   if (server->server_type != SILC_ROUTER && !server->standalone) {
4005     if (!cmd->pending) {
4006       /* Send the command to router */
4007       SilcBuffer tmpbuf;
4008       SilcUInt16 old_ident;
4009
4010       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4011
4012       old_ident = silc_command_get_ident(cmd->payload);
4013       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4014       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4015
4016       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4017                               SILC_PACKET_COMMAND, cmd->packet->flags,
4018                               tmpbuf->data, tmpbuf->len, TRUE);
4019
4020       /* Reprocess this packet after received reply from router */
4021       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4022                                   silc_command_get_ident(cmd->payload),
4023                                   silc_server_command_watch,
4024                                   silc_server_command_dup(cmd));
4025       cmd->pending = TRUE;
4026       silc_command_set_ident(cmd->payload, old_ident);
4027       silc_buffer_free(tmpbuf);
4028     } else if (context2) {
4029       /* Received reply from router, just send same data to the client. */
4030       SilcServerCommandReplyContext reply = context2;
4031       SilcStatus status;
4032
4033       SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4034       silc_command_get_status(reply->payload, &status, NULL);
4035       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4036                                             0);
4037     }
4038
4039     goto out;
4040   }
4041
4042   /* We are router and keep the watch list for local cell */
4043
4044   /* Get the client ID */
4045   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4046   if (!tmp) {
4047     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4048                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4049                                           0);
4050     goto out;
4051   }
4052   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4053   if (!client_id) {
4054     silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4055                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4056                                          0, 2, tmp, tmp_len);
4057     goto out;
4058   }
4059
4060   /* Get the client entry which must be in local list */
4061   client = silc_idlist_find_client_by_id(server->local_list,
4062                                          client_id, TRUE, NULL);
4063   if (!client) {
4064     silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4065                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
4066                                          2, tmp, tmp_len);
4067     goto out;
4068   }
4069
4070   /* Take nickname */
4071   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4072   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4073   if (!add_nick && !del_nick) {
4074     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4075                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4076                                           0);
4077     goto out;
4078   }
4079
4080   if (add_nick && add_nick_len > 128)
4081     add_nick[128] = '\0';
4082   if (del_nick && del_nick_len > 128)
4083     del_nick[128] = '\0';
4084
4085   memset(nick, 0, sizeof(nick));
4086
4087   /* Add new nickname to be watched in our cell */
4088   if (add_nick) {
4089     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4090       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4091                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4092       goto out;
4093     }
4094
4095     /* Hash the nick, we have the hash saved, not nicks because we can
4096        do one to one mapping to the nick from Client ID hash this way. */
4097     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4098     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4099
4100     /* Check whether this client is already watching this nickname */
4101     if (silc_hash_table_find_by_context(server->watcher_list, hash,
4102                                         client, NULL)) {
4103       /* Nickname is alredy being watched for this client */
4104       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4105                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
4106                                             0);
4107       goto out;
4108     }
4109
4110     /* Get the nickname from the watcher list and use the same key in
4111        new entries as well.  If key doesn't exist then create it. */
4112     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
4113       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4114
4115     /* Add the client to the watcher list with the specified nickname hash. */
4116     silc_hash_table_add(server->watcher_list, tmp, client);
4117   }
4118
4119   /* Delete nickname from watch list */
4120   if (del_nick) {
4121     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4122       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4123                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
4124       goto out;
4125     }
4126
4127     /* Hash the nick, we have the hash saved, not nicks because we can
4128        do one to one mapping to the nick from Client ID hash this way. */
4129     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4130     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4131
4132     /* Check that this client is watching for this nickname */
4133     if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4134                                          client, (void **)&tmp)) {
4135       /* Nickname is alredy being watched for this client */
4136       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4137                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4138                                            2, nick, strlen(nick));
4139       goto out;
4140     }
4141
4142     /* Delete the nickname from the watcher list. */
4143     silc_hash_table_del_by_context(server->watcher_list, hash, client);
4144
4145     /* Now check whether there still exists entries with this key, if not
4146        then free the key to not leak memory. */
4147     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4148       silc_free(tmp);
4149   }
4150
4151   /* Distribute the watch list to backup routers too */
4152   if (server->backup) {
4153     SilcBuffer tmpbuf;
4154     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4155     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4156     silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
4157                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
4158                             FALSE, TRUE);
4159     silc_buffer_free(tmpbuf);
4160   }
4161
4162   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4163                                         SILC_STATUS_OK, 0);
4164
4165  out:
4166   silc_free(client_id);
4167   silc_server_command_free(cmd);
4168 }
4169
4170 /* Server side of SILCOPER command. Client uses this comand to obtain router
4171    operator privileges to this router. */
4172
4173 SILC_SERVER_CMD_FUNC(silcoper)
4174 {
4175   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4176   SilcServer server = cmd->server;
4177   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4178   unsigned char *username, *auth;
4179   SilcUInt32 tmp_len;
4180   SilcServerConfigAdmin *admin;
4181   SilcIDListData idata = (SilcIDListData)client;
4182   bool result = FALSE;
4183   SilcPublicKey cached_key;
4184
4185   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4186     goto out;
4187
4188   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4189
4190   if (server->server_type != SILC_ROUTER) {
4191     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4192                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4193     goto out;
4194   }
4195
4196   /* Get the username */
4197   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4198   if (!username) {
4199     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4200                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4201                                           0);
4202     goto out;
4203   }
4204
4205   /* Get the admin configuration */
4206   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4207                                         username, client->nickname);
4208   if (!admin) {
4209     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4210                                           username, client->nickname);
4211     if (!admin) {
4212       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4213                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
4214       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4215                      "nickname '%s' from %s", username,
4216                      client->nickname, cmd->sock->hostname));
4217       goto out;
4218     }
4219   }
4220
4221   /* Get the authentication payload */
4222   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4223   if (!auth) {
4224     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4225                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4226                                           0);
4227     goto out;
4228   }
4229
4230   /* Verify the authentication data. If both passphrase and public key
4231      is set then try both of them. */
4232   if (admin->passphrase)
4233     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4234                                    admin->passphrase, admin->passphrase_len,
4235                                    idata->hash, client->id, SILC_ID_CLIENT);
4236   if (!result && admin->publickeys) {
4237     cached_key = silc_server_get_public_key(server, admin->publickeys);
4238     if (!cached_key)
4239       goto out;
4240     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4241                                    cached_key, 0, idata->hash,
4242                                    client->id, SILC_ID_CLIENT);
4243   }
4244   if (!result) {
4245     /* Authentication failed */
4246     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4247                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
4248     goto out;
4249   }
4250
4251   /* Client is now router operator */
4252   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4253
4254   /* Update statistics */
4255   if (SILC_IS_LOCAL(client))
4256     server->stat.my_router_ops++;
4257   if (server->server_type == SILC_ROUTER)
4258     server->stat.router_ops++;
4259
4260   /* Send UMODE change to primary router */
4261   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4262                                 SILC_BROADCAST(server), client->id,
4263                                 client->mode);
4264
4265   /* Check if anyone is watching this nickname */
4266   if (server->server_type == SILC_ROUTER)
4267     silc_server_check_watcher_list(server, client, NULL,
4268                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4269
4270   /* Send reply to the sender */
4271   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4272                                         SILC_STATUS_OK, 0);
4273
4274  out:
4275   silc_server_command_free(cmd);
4276 }
4277
4278 /* Server side of command BAN. This is used to manage the ban list of the
4279    channel. To add clients and remove clients from the ban list. */
4280
4281 SILC_SERVER_CMD_FUNC(ban)
4282 {
4283   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4284   SilcServer server = cmd->server;
4285   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4286   SilcBuffer packet, list, tmp2;
4287   SilcChannelEntry channel;
4288   SilcChannelClientEntry chl;
4289   SilcChannelID *channel_id = NULL;
4290   unsigned char *id, *tmp, *atype = NULL;
4291   SilcUInt32 id_len, len, len2;
4292   SilcArgumentPayload args;
4293   SilcHashTableList htl;
4294   SilcUInt32 type;
4295   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4296   SilcBufferStruct blist;
4297
4298   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4299     goto out;
4300
4301   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4302
4303   /* Get Channel ID */
4304   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4305   if (id) {
4306     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4307     if (!channel_id) {
4308       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4309                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4310       goto out;
4311     }
4312   }
4313
4314   /* Get channel entry. The server must know about the channel since the
4315      client is expected to be on the channel. */
4316   channel = silc_idlist_find_channel_by_id(server->local_list,
4317                                            channel_id, NULL);
4318   if (!channel) {
4319     channel = silc_idlist_find_channel_by_id(server->global_list,
4320                                              channel_id, NULL);
4321     if (!channel) {
4322       silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4323                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4324                                            0, 2, id, id_len);
4325       goto out;
4326     }
4327   }
4328
4329   /* Check whether this client is on the channel */
4330   if (!silc_server_client_on_channel(client, channel, &chl)) {
4331     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4332                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4333                                          2, id, id_len);
4334     goto out;
4335   }
4336
4337   /* The client must be at least channel operator. */
4338   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4339     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4340                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4341                                          2, id, id_len);
4342     goto out;
4343   }
4344
4345   /* Get the ban information */
4346   tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4347   if (tmp && len2 > 2) {
4348     /* Parse the arguments to see they are constructed correctly */
4349     SILC_GET16_MSB(argc, tmp);
4350     args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4351     if (!args) {
4352       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4353                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4354                                             0);
4355       goto out;
4356     }
4357
4358     /* Get the type of action */
4359     atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4360     if (atype && len == 1) {
4361       if (atype[0] == 0x00) {
4362         /* Allocate hash table for ban list if it doesn't exist yet */
4363         if (!channel->ban_list)
4364           channel->ban_list =
4365             silc_hash_table_alloc(0, silc_hash_ptr,
4366                                   NULL, NULL, NULL,
4367                                   silc_server_inviteban_destruct, channel,
4368                                   TRUE);
4369
4370         /* Check for resource limit */
4371         if (silc_hash_table_count(channel->ban_list) > 64) {
4372           silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4373                                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
4374                                                 0);
4375           goto out;
4376         }
4377       }
4378
4379       /* Now add or delete the information. */
4380       silc_server_inviteban_process(server, channel->ban_list,
4381                                     (SilcUInt8)atype[0], args);
4382     }
4383     silc_argument_payload_free(args);
4384   }
4385
4386   /* Encode ban list */
4387   list = NULL;
4388   if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4389     list = silc_buffer_alloc_size(2);
4390     silc_buffer_format(list,
4391                        SILC_STR_UI_SHORT(silc_hash_table_count(
4392                                           channel->ban_list)),
4393                        SILC_STR_END);
4394     silc_hash_table_list(channel->ban_list, &htl);
4395     while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
4396       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4397                                               type);
4398     silc_hash_table_list_reset(&htl);
4399   }
4400
4401   /* Send BAN notify type to local servers (but not clients) and to
4402      network. */
4403   if (atype && tmp && len2) {
4404     silc_buffer_set(&blist, tmp, len2);
4405
4406     /* Send to local servers if we are router */
4407     if (server->server_type == SILC_ROUTER)
4408       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4409                                          SILC_NOTIFY_TYPE_BAN, 3,
4410                                          id, id_len,
4411                                          atype, 1,
4412                                          tmp ? blist.data : NULL,
4413                                          tmp ? blist.len : 0);
4414
4415     /* Send to network. */
4416     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4417                                 SILC_BROADCAST(server), channel, atype,
4418                                 &blist);
4419   }
4420
4421   /* Send the reply back to the client */
4422   packet =
4423     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4424                                          SILC_STATUS_OK, 0, ident, 2,
4425                                          2, id, id_len,
4426                                          3, list ? list->data : NULL,
4427                                          list ? list->len : 0);
4428   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4429                           packet->data, packet->len, FALSE);
4430
4431   silc_buffer_free(packet);
4432   silc_buffer_free(list);
4433
4434  out:
4435   silc_free(channel_id);
4436   silc_server_command_free(cmd);
4437 }
4438
4439 /* Server side command of LEAVE. Removes client from a channel. */
4440
4441 SILC_SERVER_CMD_FUNC(leave)
4442 {
4443   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4444   SilcServer server = cmd->server;
4445   SilcSocketConnection sock = cmd->sock;
4446   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4447   SilcChannelID *id = NULL;
4448   SilcChannelEntry channel;
4449   SilcUInt32 len;
4450   unsigned char *tmp;
4451
4452   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4453     goto out;
4454
4455   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4456
4457   /* Get Channel ID */
4458   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4459   if (!tmp) {
4460     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4461                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4462     goto out;
4463   }
4464   id = silc_id_payload_parse_id(tmp, len, NULL);
4465   if (!id) {
4466     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4467                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4468     goto out;
4469   }
4470
4471   /* Get channel entry */
4472   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4473   if (!channel) {
4474     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4475     if (!channel) {
4476       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4477                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4478                                            0, 2, tmp, len);
4479       goto out;
4480     }
4481   }
4482
4483   /* Check whether this client is on the channel */
4484   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4485     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4486                                          SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4487                                          2, tmp, len);
4488     goto out;
4489   }
4490
4491   /* Notify routers that they should remove this client from their list
4492      of clients on the channel. Send LEAVE notify type. */
4493   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4494                                 SILC_BROADCAST(server), channel, id_entry->id);
4495
4496   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4497                                        SILC_STATUS_OK, 0, 2, tmp, len);
4498
4499   /* Remove client from channel */
4500   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4501                                            TRUE))
4502     /* If the channel does not exist anymore we won't send anything */
4503     goto out;
4504
4505   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4506     /* Re-generate channel key */
4507     if (!silc_server_create_channel_key(server, channel, 0))
4508       goto out;
4509
4510     /* Send the channel key */
4511     silc_server_send_channel_key(server, NULL, channel,
4512                                  server->server_type == SILC_ROUTER ?
4513                                  FALSE : !server->standalone);
4514   }
4515
4516  out:
4517   silc_free(id);
4518   silc_server_command_free(cmd);
4519 }
4520
4521 /* Server side of command USERS. Resolves clients and their USERS currently
4522    joined on the requested channel. The list of Client ID's and their modes
4523    on the channel is sent back. */
4524
4525 SILC_SERVER_CMD_FUNC(users)
4526 {
4527   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4528   SilcServer server = cmd->server;
4529   SilcChannelEntry channel;
4530   SilcChannelID *id = NULL;
4531   SilcBuffer packet, idp;
4532   unsigned char *channel_id;
4533   SilcUInt32 channel_id_len;
4534   SilcBuffer client_id_list;
4535   SilcBuffer client_mode_list;
4536   unsigned char lc[4];
4537   SilcUInt32 list_count = 0;
4538   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4539   char *channel_name;
4540
4541   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4542
4543   /* Get Channel ID */
4544   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4545
4546   /* Get channel name */
4547   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4548
4549   if (!channel_id && !channel_name) {
4550     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4551                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4552     goto out;
4553   }
4554
4555   if (channel_id) {
4556     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4557     if (!id) {
4558       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4559                                            SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4560                                            2, channel_id, channel_id_len);
4561       goto out;
4562     }
4563   }
4564
4565   /* If we are server and we don't know about this channel we will send
4566      the command to our router. If we know about the channel then we also
4567      have the list of users already. */
4568   if (id)
4569     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4570   else
4571     channel = silc_idlist_find_channel_by_name(server->local_list,
4572                                                channel_name, NULL);
4573
4574   if (!channel || (!server->standalone && (channel->disabled ||
4575                     !channel->users_resolved))) {
4576     if (server->server_type != SILC_ROUTER && !server->standalone &&
4577         !cmd->pending) {
4578       SilcBuffer tmpbuf;
4579
4580       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4581       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4582
4583       /* Send USERS command */
4584       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4585                               SILC_PACKET_COMMAND, cmd->packet->flags,
4586                               tmpbuf->data, tmpbuf->len, TRUE);
4587
4588       /* Reprocess this packet after received reply */
4589       silc_server_command_pending(server, SILC_COMMAND_USERS,
4590                                   silc_command_get_ident(cmd->payload),
4591                                   silc_server_command_users,
4592                                   silc_server_command_dup(cmd));
4593       cmd->pending = TRUE;
4594       silc_command_set_ident(cmd->payload, ident);
4595       silc_buffer_free(tmpbuf);
4596       silc_free(id);
4597       goto out;
4598     }
4599
4600     /* Check the global list as well. */
4601     if (id)
4602       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4603     else
4604       channel = silc_idlist_find_channel_by_name(server->global_list,
4605                                                  channel_name, NULL);
4606     if (!channel) {
4607       /* Channel really does not exist */
4608       if (id)
4609         silc_server_command_send_status_data(
4610                                     cmd, SILC_COMMAND_USERS,
4611                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4612                                     2, channel_id, channel_id_len);
4613       else
4614         silc_server_command_send_status_data(
4615                                     cmd, SILC_COMMAND_USERS,
4616                                     SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4617                                     2, channel_name, strlen(channel_name));
4618       goto out;
4619     }
4620   }
4621
4622   /* If the channel is private or secret do not send anything, unless the
4623      user requesting this command is on the channel or is server */
4624   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4625     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4626         && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4627                                           NULL)) {
4628       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4629                                            SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4630                                            2, channel->channel_name,
4631                                            strlen(channel->channel_name));
4632       goto out;
4633     }
4634   }
4635
4636   /* Get the users list */
4637   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4638                                         &client_mode_list, &list_count)) {
4639     list_count = 0;
4640     client_id_list = NULL;
4641     client_mode_list = NULL;
4642   }
4643
4644   /* List count */
4645   SILC_PUT32_MSB(list_count, lc);
4646
4647   /* Send reply */
4648   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4649   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4650                                                 SILC_STATUS_OK, 0, ident, 4,
4651                                                 2, idp->data, idp->len,
4652                                                 3, lc, 4,
4653                                                 4, client_id_list ?
4654                                                 client_id_list->data : NULL,
4655                                                 client_id_list ?
4656                                                 client_id_list->len : 0,
4657                                                 5, client_mode_list ?
4658                                                 client_mode_list->data : NULL,
4659                                                 client_mode_list ?
4660                                                 client_mode_list->len : 0);
4661   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4662                           packet->data, packet->len, FALSE);
4663
4664   silc_buffer_free(idp);
4665   silc_buffer_free(packet);
4666   if (client_id_list)
4667     silc_buffer_free(client_id_list);
4668   if (client_mode_list)
4669     silc_buffer_free(client_mode_list);
4670   silc_free(id);
4671
4672  out:
4673   silc_server_command_free(cmd);
4674 }
4675
4676 /* Server side of command GETKEY. This fetches the client's public key
4677    from the server where to the client is connected. */
4678
4679 SILC_SERVER_CMD_FUNC(getkey)
4680 {
4681   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4682   SilcServer server = cmd->server;
4683   SilcBuffer packet;
4684   SilcClientEntry client;
4685   SilcServerEntry server_entry;
4686   SilcClientID *client_id = NULL;
4687   SilcServerID *server_id = NULL;
4688   SilcIDPayload idp = NULL;
4689   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4690   unsigned char *tmp;
4691   SilcUInt32 tmp_len;
4692   SilcBuffer pk = NULL;
4693   SilcIdType id_type;
4694   SilcPublicKey public_key;
4695
4696   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4697   if (!tmp) {
4698     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4699                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4700                                           0);
4701     goto out;
4702   }
4703   idp = silc_id_payload_parse(tmp, tmp_len);
4704   if (!idp) {
4705     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4706                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4707                                           0);
4708     goto out;
4709   }
4710
4711   id_type = silc_id_payload_get_type(idp);
4712   if (id_type == SILC_ID_CLIENT) {
4713     client_id = silc_id_payload_get_id(idp);
4714
4715     /* If the client is not found from local list there is no chance it
4716        would be locally connected client so send the command further. */
4717     client = silc_idlist_find_client_by_id(server->local_list,
4718                                            client_id, TRUE, NULL);
4719     if (!client)
4720       client = silc_idlist_find_client_by_id(server->global_list,
4721                                              client_id, TRUE, NULL);
4722
4723     if ((!client && !cmd->pending && !server->standalone) ||
4724         (client && !client->connection && !cmd->pending &&
4725          !(client->mode & SILC_UMODE_DETACHED)) ||
4726         (client && !client->data.public_key && !cmd->pending)) {
4727       SilcBuffer tmpbuf;
4728       SilcUInt16 old_ident;
4729       SilcSocketConnection dest_sock;
4730
4731       dest_sock = silc_server_get_client_route(server, NULL, 0,
4732                                                client_id, NULL, NULL);
4733       if (!dest_sock)
4734         goto out;
4735
4736       old_ident = silc_command_get_ident(cmd->payload);
4737       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4738       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4739
4740       silc_server_packet_send(server, dest_sock,
4741                               SILC_PACKET_COMMAND, cmd->packet->flags,
4742                               tmpbuf->data, tmpbuf->len, TRUE);
4743
4744       /* Reprocess this packet after received reply from router */
4745       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4746                                   silc_command_get_ident(cmd->payload),
4747                                   silc_server_command_getkey,
4748                                   silc_server_command_dup(cmd));
4749       cmd->pending = TRUE;
4750       silc_command_set_ident(cmd->payload, old_ident);
4751       silc_buffer_free(tmpbuf);
4752       goto out;
4753     }
4754
4755     if (!client) {
4756       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4757                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4758                                            0, 2, tmp, tmp_len);
4759       goto out;
4760     }
4761
4762     /* The client is locally connected, just get the public key and
4763        send it back. If they key does not exist then do not send it,
4764        send just OK reply */
4765     public_key = client->data.public_key;
4766     if (public_key)
4767       pk = silc_pkcs_public_key_payload_encode(public_key);
4768   } else if (id_type == SILC_ID_SERVER) {
4769     server_id = silc_id_payload_get_id(idp);
4770
4771     /* If the server is not found from local list there is no chance it
4772        would be locally connected server so send the command further. */
4773     server_entry = silc_idlist_find_server_by_id(server->local_list,
4774                                                  server_id, TRUE, NULL);
4775     if (!server_entry)
4776       server_entry = silc_idlist_find_server_by_id(server->global_list,
4777                                                    server_id, TRUE, NULL);
4778
4779     if (server_entry != server->id_entry &&
4780         ((!server_entry && !cmd->pending && !server->standalone) ||
4781          (server_entry && !server_entry->connection && !cmd->pending &&
4782           !server->standalone) ||
4783          (server_entry && !server_entry->data.public_key && !cmd->pending &&
4784           !server->standalone))) {
4785       SilcBuffer tmpbuf;
4786       SilcUInt16 old_ident;
4787
4788       old_ident = silc_command_get_ident(cmd->payload);
4789       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4790       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4791
4792       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4793                               SILC_PACKET_COMMAND, cmd->packet->flags,
4794                               tmpbuf->data, tmpbuf->len, TRUE);
4795
4796       /* Reprocess this packet after received reply from router */
4797       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4798                                   silc_command_get_ident(cmd->payload),
4799                                   silc_server_command_getkey,
4800                                   silc_server_command_dup(cmd));
4801       cmd->pending = TRUE;
4802       silc_command_set_ident(cmd->payload, old_ident);
4803       silc_buffer_free(tmpbuf);
4804       goto out;
4805     }
4806
4807     if (!server_entry) {
4808       silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4809                                            SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4810                                            0, 2, tmp, tmp_len);
4811       goto out;
4812     }
4813
4814     /* If they key does not exist then do not send it, send just OK reply */
4815     public_key = (!server_entry->data.public_key ?
4816                   (server_entry == server->id_entry ? server->public_key :
4817                    NULL) : server_entry->data.public_key);
4818     if (public_key)
4819       pk = silc_pkcs_public_key_payload_encode(public_key);
4820   } else {
4821     goto out;
4822   }
4823
4824   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4825   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4826                                                 SILC_STATUS_OK, 0, ident, 2,
4827                                                 2, tmp, tmp_len,
4828                                                 3, pk ? pk->data : NULL,
4829                                                 pk ? pk->len : 0);
4830   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4831                           packet->data, packet->len, FALSE);
4832   silc_buffer_free(packet);
4833
4834  out:
4835   if (idp)
4836     silc_id_payload_free(idp);
4837   silc_buffer_free(pk);
4838   silc_free(client_id);
4839   silc_free(server_id);
4840   silc_server_command_free(cmd);
4841 }
4842
4843
4844 /* Private range commands, specific to this implementation */
4845
4846 /* Server side command of CONNECT. Connects us to the specified remote
4847    server or router. */
4848
4849 SILC_SERVER_CMD_FUNC(connect)
4850 {
4851   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4852   SilcServer server = cmd->server;
4853   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4854   unsigned char *tmp, *host;
4855   SilcUInt32 tmp_len;
4856   SilcUInt32 port = SILC_PORT;
4857
4858   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4859     goto out;
4860
4861   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4862
4863   /* Check whether client has the permissions. */
4864   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4865       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4866     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4867                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4868     goto out;
4869   }
4870
4871   if (server->server_type == SILC_ROUTER && !server->backup_router &&
4872       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4873     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4874                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4875     goto out;
4876   }
4877
4878   /* Get the remote server */
4879   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4880   if (!host) {
4881     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4882                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4883                                           0);
4884     goto out;
4885   }
4886
4887   /* Get port */
4888   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4889   if (tmp)
4890     SILC_GET32_MSB(port, tmp);
4891
4892   /* Create the connection. It is done with timeout and is async. */
4893   silc_server_create_connection(server, host, port);
4894
4895   /* Send reply to the sender */
4896   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4897                                         SILC_STATUS_OK, 0);
4898
4899  out:
4900   silc_server_command_free(cmd);
4901 }
4902
4903 /* Server side command of CLOSE. Closes connection to a specified server. */
4904
4905 SILC_SERVER_CMD_FUNC(close)
4906 {
4907   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4908   SilcServer server = cmd->server;
4909   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4910   SilcServerEntry server_entry;
4911   SilcSocketConnection sock;
4912   unsigned char *tmp;
4913   SilcUInt32 tmp_len;
4914   unsigned char *name;
4915   SilcUInt32 port = SILC_PORT;
4916
4917   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4918     goto out;
4919
4920   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4921
4922   /* Check whether client has the permissions. */
4923   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4924       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4925     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4926                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
4927                                           0);
4928     goto out;
4929   }
4930
4931   /* Get the remote server */
4932   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4933   if (!name) {
4934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4935                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4936                                           0);
4937     goto out;
4938   }
4939
4940   /* Get port */
4941   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4942   if (tmp)
4943     SILC_GET32_MSB(port, tmp);
4944
4945   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4946                                                  name, port, FALSE, NULL);
4947   if (!server_entry)
4948     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4949                                                    name, port, FALSE, NULL);
4950   if (!server_entry) {
4951     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4952                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
4953     goto out;
4954   }
4955
4956   if (server_entry == server->id_entry) {
4957     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4958                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
4959     goto out;
4960   }
4961
4962   /* Send reply to the sender */
4963   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4964                                         SILC_STATUS_OK, 0);
4965
4966   /* Close the connection to the server */
4967   sock = (SilcSocketConnection)server_entry->connection;
4968
4969   server->backup_noswitch = TRUE;
4970   if (server->router == server_entry) {
4971     server->id_entry->router = NULL;
4972     server->router = NULL;
4973     server->standalone = TRUE;
4974   }
4975   silc_server_disconnect_remote(server, sock,
4976                                 SILC_STATUS_ERR_BANNED_FROM_SERVER,
4977                                 "Closed by administrator");
4978   if (sock->user_data)
4979     silc_server_free_sock_user_data(server, sock, NULL);
4980   server->backup_noswitch = FALSE;
4981
4982  out:
4983   silc_server_command_free(cmd);
4984 }
4985
4986 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4987    active connections. */
4988
4989 SILC_SERVER_CMD_FUNC(shutdown)
4990 {
4991   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4992   SilcServer server = cmd->server;
4993   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4994
4995   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4996     goto out;
4997
4998   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4999
5000   /* Check whether client has the permission. */
5001   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5002       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5003     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5004                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5005                                           0);
5006     goto out;
5007   }
5008
5009   /* Send reply to the sender */
5010   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5011                                         SILC_STATUS_OK, 0);
5012
5013   /* Then, gracefully, or not, bring the server down. */
5014   silc_server_stop(server);
5015   exit(0);
5016
5017  out:
5018   silc_server_command_free(cmd);
5019 }