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