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