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