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