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