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