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