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