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