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