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