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, server->sha1hash,
3227                                 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     /* If client became founder by providing correct founder auth data
3429        notify the mode change to the channel. */
3430     if (founder) {
3431       SILC_PUT32_MSB(chl->mode, mode);
3432       tmp = silc_pkcs_public_key_encode(channel->founder_key, &tmp_len);
3433       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3434                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3435                                          clidp->data, clidp->len,
3436                                          mode, 4, clidp->data, clidp->len,
3437                                          tmp, tmp_len);
3438       silc_free(tmp);
3439       
3440       /* Set CUMODE notify type to network */
3441       if (!server->standalone)
3442         silc_server_send_notify_cumode(server, server->router->connection,
3443                                        server->server_type == SILC_ROUTER ? 
3444                                        TRUE : FALSE, channel,
3445                                        chl->mode, client->id, SILC_ID_CLIENT,
3446                                        client->id, channel->founder_key);
3447     }
3448   }
3449
3450   silc_buffer_free(reply);
3451   silc_buffer_free(clidp);
3452   silc_buffer_free(chidp);
3453   silc_buffer_free(keyp);
3454   silc_buffer_free(user_list);
3455   silc_buffer_free(mode_list);
3456
3457  out:
3458   silc_free(passphrase);
3459 }
3460
3461 /* Server side of command JOIN. Joins client into requested channel. If 
3462    the channel does not exist it will be created. */
3463
3464 SILC_SERVER_CMD_FUNC(join)
3465 {
3466   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3467   SilcServer server = cmd->server;
3468   unsigned char *auth;
3469   SilcUInt32 tmp_len, auth_len;
3470   char *tmp, *channel_name = NULL, *cipher, *hmac;
3471   SilcChannelEntry channel;
3472   SilcUInt32 umode = 0;
3473   bool created = FALSE, create_key = TRUE;
3474   SilcClientID *client_id;
3475
3476   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3477
3478   /* Get channel name */
3479   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3480   if (!tmp) {
3481     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3482                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3483                                           0);
3484     goto out;
3485   }
3486   channel_name = tmp;
3487
3488   if (tmp_len > 256)
3489     channel_name[255] = '\0';
3490
3491   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3492     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3493                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
3494     goto out;
3495   }
3496
3497   /* Get Client ID of the client who is joining to the channel */
3498   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3499   if (!tmp) {
3500     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3501                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3502                                           0);
3503     goto out;
3504   }
3505   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3506   if (!client_id) {
3507     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3508                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3509                                           0);
3510     goto out;
3511   }
3512
3513   /* Get cipher, hmac name and auth payload */
3514   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3515   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3516   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3517
3518   /* See if the channel exists */
3519   channel = silc_idlist_find_channel_by_name(server->local_list, 
3520                                              channel_name, NULL);
3521
3522   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3523     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3524     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3525
3526     if (!channel || 
3527         (channel->disabled && server->server_type != SILC_ROUTER)) {
3528       /* Channel not found */
3529
3530       /* If we are standalone server we don't have a router, we just create 
3531          the channel by ourselves. */
3532       if (server->standalone) {
3533         channel = silc_server_create_new_channel(server, server->id, cipher, 
3534                                                  hmac, channel_name, TRUE);
3535         if (!channel) {
3536           silc_server_command_send_status_reply(
3537                                          cmd, SILC_COMMAND_JOIN,
3538                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3539                                          0);
3540           goto out;
3541         }
3542         
3543         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3544         created = TRUE;
3545         create_key = FALSE;
3546         
3547       } else {
3548
3549         /* The channel does not exist on our server. If we are normal server 
3550            we will send JOIN command to our router which will handle the
3551            joining procedure (either creates the channel if it doesn't exist 
3552            or joins the client to it). */
3553         if (server->server_type != SILC_ROUTER) {
3554           SilcBuffer tmpbuf;
3555           SilcUInt16 old_ident;
3556
3557           /* If this is pending command callback then we've resolved
3558              it and it didn't work, return since we've notified the
3559              client already in the command reply callback. */
3560           if (cmd->pending)
3561             goto out;
3562           
3563           old_ident = silc_command_get_ident(cmd->payload);
3564           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3565           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3566           
3567           /* Send JOIN command to our router */
3568           silc_server_packet_send(server, (SilcSocketConnection)
3569                                   server->router->connection,
3570                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3571                                   tmpbuf->data, tmpbuf->len, TRUE);
3572           
3573           /* Reprocess this packet after received reply from router */
3574           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3575                                       silc_command_get_ident(cmd->payload),
3576                                       silc_server_command_join,
3577                                       silc_server_command_dup(cmd));
3578           cmd->pending = TRUE;
3579           silc_command_set_ident(cmd->payload, old_ident);
3580           silc_buffer_free(tmpbuf);
3581           goto out;
3582         }
3583         
3584         /* We are router and the channel does not seem exist so we will check
3585            our global list as well for the channel. */
3586         channel = silc_idlist_find_channel_by_name(server->global_list, 
3587                                                    channel_name, NULL);
3588         if (!channel) {
3589           /* Channel really does not exist, create it */
3590           channel = silc_server_create_new_channel(server, server->id, cipher, 
3591                                                    hmac, channel_name, TRUE);
3592           if (!channel) {
3593             silc_server_command_send_status_reply(
3594                                        cmd, SILC_COMMAND_JOIN,
3595                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3596             goto out;
3597           }
3598
3599           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3600           created = TRUE;
3601           create_key = FALSE;
3602         }
3603       }
3604     }
3605   } else {
3606     if (!channel) {
3607       /* Channel not found */
3608
3609       /* If the command came from router and we are normal server then
3610          something went wrong with the joining as the channel was not found.
3611          We can't do anything else but ignore this. */
3612       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3613           server->server_type != SILC_ROUTER)
3614         goto out;
3615       
3616       /* We are router and the channel does not seem exist so we will check
3617          our global list as well for the channel. */
3618       channel = silc_idlist_find_channel_by_name(server->global_list, 
3619                                                  channel_name, NULL);
3620       if (!channel) {
3621         /* Channel really does not exist, create it */
3622         channel = silc_server_create_new_channel(server, server->id, cipher, 
3623                                                  hmac, channel_name, TRUE);
3624         if (!channel) {
3625           silc_server_command_send_status_reply(
3626                                        cmd, SILC_COMMAND_JOIN,
3627                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3628           goto out;
3629         }
3630
3631         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3632         created = TRUE;
3633         create_key = FALSE;
3634       }
3635     }
3636   }
3637
3638   /* Check whether the channel was created by our router */
3639   if (cmd->pending && context2) {
3640     SilcServerCommandReplyContext reply = context2;
3641
3642     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3643       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3644       SILC_GET32_MSB(created, tmp);
3645       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3646         create_key = FALSE;     /* Router returned the key already */
3647     }
3648
3649     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3650         !silc_hash_table_count(channel->user_list))
3651       created = TRUE;
3652   }
3653
3654   /* If the channel does not have global users and is also empty the client
3655      will be the channel founder and operator. */
3656   if (!channel->disabled &&
3657       !channel->global_users && !silc_hash_table_count(channel->user_list))
3658     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3659
3660   /* Join to the channel */
3661   silc_server_command_join_channel(server, cmd, channel, client_id,
3662                                    created, create_key, umode,
3663                                    auth, auth_len);
3664
3665   silc_free(client_id);
3666
3667  out:
3668   silc_server_command_free(cmd);
3669 }
3670
3671 /* Server side of command MOTD. Sends server's current "message of the
3672    day" to the client. */
3673
3674 SILC_SERVER_CMD_FUNC(motd)
3675 {
3676   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3677   SilcServer server = cmd->server;
3678   SilcBuffer packet, idp;
3679   char *motd, *dest_server;
3680   SilcUInt32 motd_len;
3681   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3682   
3683   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3684
3685   /* Get server name */
3686   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3687   if (!dest_server) {
3688     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3689                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3690     goto out;
3691   }
3692
3693   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3694     /* Send our MOTD */
3695
3696     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3697
3698     if (server->config && server->config->server_info &&
3699         server->config->server_info->motd_file) {
3700       /* Send motd */
3701       motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3702       if (!motd)
3703         goto out;
3704       
3705       motd[motd_len] = 0;
3706       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3707                                                     SILC_STATUS_OK, 0, 
3708                                                     ident, 2,
3709                                                     2, idp, idp->len,
3710                                                     3, motd, motd_len);
3711     } else {
3712       /* No motd */
3713       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3714                                                     SILC_STATUS_OK, 0, 
3715                                                     ident, 1,
3716                                                     2, idp, idp->len);
3717     }
3718
3719     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3720                             packet->data, packet->len, FALSE);
3721     silc_buffer_free(packet);
3722     silc_buffer_free(idp);
3723   } else {
3724     SilcServerEntry entry;
3725
3726     /* Check whether we have this server cached */
3727     entry = silc_idlist_find_server_by_name(server->global_list,
3728                                             dest_server, TRUE, NULL);
3729     if (!entry) {
3730       entry = silc_idlist_find_server_by_name(server->local_list,
3731                                               dest_server, TRUE, NULL);
3732     }
3733
3734     if (server->server_type != SILC_SERVER && !cmd->pending && 
3735         entry && !entry->motd) {
3736       /* Send to the server */
3737       SilcBuffer tmpbuf;
3738       SilcUInt16 old_ident;
3739
3740       old_ident = silc_command_get_ident(cmd->payload);
3741       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3742       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3743
3744       silc_server_packet_send(server, entry->connection,
3745                               SILC_PACKET_COMMAND, cmd->packet->flags,
3746                               tmpbuf->data, tmpbuf->len, TRUE);
3747
3748       /* Reprocess this packet after received reply from router */
3749       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3750                                   silc_command_get_ident(cmd->payload),
3751                                   silc_server_command_motd,
3752                                   silc_server_command_dup(cmd));
3753       cmd->pending = TRUE;
3754       silc_command_set_ident(cmd->payload, old_ident);
3755       silc_buffer_free(tmpbuf);
3756       goto out;
3757     }
3758
3759     if (!entry && !cmd->pending && !server->standalone) {
3760       /* Send to the primary router */
3761       SilcBuffer tmpbuf;
3762       SilcUInt16 old_ident;
3763
3764       old_ident = silc_command_get_ident(cmd->payload);
3765       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3766       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3767
3768       silc_server_packet_send(server, server->router->connection,
3769                               SILC_PACKET_COMMAND, cmd->packet->flags,
3770                               tmpbuf->data, tmpbuf->len, TRUE);
3771
3772       /* Reprocess this packet after received reply from router */
3773       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3774                                   silc_command_get_ident(cmd->payload),
3775                                   silc_server_command_motd,
3776                                   silc_server_command_dup(cmd));
3777       cmd->pending = TRUE;
3778       silc_command_set_ident(cmd->payload, old_ident);
3779       silc_buffer_free(tmpbuf);
3780       goto out;
3781     }
3782
3783     if (!entry) {
3784       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3785                                             SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3786       goto out;
3787     }
3788
3789     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3790     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3791                                                   SILC_STATUS_OK, 0, ident, 2,
3792                                                   2, idp, idp->len,
3793                                                   3, entry->motd,
3794                                                   entry->motd ? 
3795                                                   strlen(entry->motd) : 0);
3796     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3797                             packet->data, packet->len, FALSE);
3798     silc_buffer_free(packet);
3799     silc_buffer_free(idp);
3800   }
3801
3802  out:
3803   silc_server_command_free(cmd);
3804 }
3805
3806 /* Server side of command UMODE. Client can use this command to set/unset
3807    user mode. Client actually cannot set itself to be as server/router
3808    operator so this can be used only to unset the modes. */
3809
3810 SILC_SERVER_CMD_FUNC(umode)
3811 {
3812   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3813   SilcServer server = cmd->server;
3814   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3815   SilcBuffer packet;
3816   unsigned char *tmp_mask, m[4];
3817   SilcUInt32 mask = 0;
3818   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3819   bool set_mask = FALSE;
3820
3821   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3822     goto out;
3823
3824   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3825
3826   /* Get the client's mode mask */
3827   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3828   if (tmp_mask) {
3829     SILC_GET32_MSB(mask, tmp_mask);
3830     set_mask = TRUE;
3831   }
3832
3833   if (set_mask) {
3834     /* Check that mode changing is allowed. */
3835     if (!silc_server_check_umode_rights(server, client, mask)) {
3836       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3837                                             SILC_STATUS_ERR_PERM_DENIED, 0);
3838       goto out;
3839     }
3840
3841     /* Anonymous mode cannot be set by client */
3842     if (mask & SILC_UMODE_ANONYMOUS) {
3843       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3844         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3845                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3846         goto out;
3847       }
3848     } else {
3849       if (client->mode & SILC_UMODE_ANONYMOUS) {
3850         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3851                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3852         goto out;
3853       }
3854     }
3855
3856     /* Change the mode */
3857     client->mode = mask;
3858
3859     /* Send UMODE change to primary router */
3860     if (!server->standalone)
3861       silc_server_send_notify_umode(server, server->router->connection, TRUE,
3862                                     client->id, client->mode);
3863
3864     /* Check if anyone is watching this nickname */
3865     if (server->server_type == SILC_ROUTER)
3866       silc_server_check_watcher_list(server, client, NULL,
3867                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
3868   }
3869
3870   /* Send command reply to sender */
3871   SILC_PUT32_MSB(client->mode, m);
3872   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3873                                                 SILC_STATUS_OK, 0, ident, 1,
3874                                                 2, m, sizeof(m));
3875   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3876                           packet->data, packet->len, FALSE);
3877   silc_buffer_free(packet);
3878
3879  out:
3880   silc_server_command_free(cmd);
3881 }
3882
3883 /* Server side command of CMODE. Changes channel mode */
3884
3885 SILC_SERVER_CMD_FUNC(cmode)
3886 {
3887   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3888   SilcServer server = cmd->server;
3889   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3890   SilcIDListData idata = (SilcIDListData)client;
3891   SilcChannelID *channel_id = NULL;
3892   SilcChannelEntry channel;
3893   SilcChannelClientEntry chl;
3894   SilcBuffer packet, cidp;
3895   unsigned char *tmp, *tmp_id, *tmp_mask;
3896   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3897   SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3898   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3899   bool set_mask = FALSE;
3900   SilcPublicKey founder_key = NULL;
3901   unsigned char *fkey = NULL;
3902   SilcUInt32 fkey_len = 0;
3903
3904   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3905
3906   /* Get Channel ID */
3907   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3908   if (!tmp_id) {
3909     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3911     goto out;
3912   }
3913   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3914   if (!channel_id) {
3915     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3917     goto out;
3918   }
3919
3920   /* Get the channel mode mask */
3921   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3922   if (tmp_mask) {
3923     SILC_GET32_MSB(mode_mask, tmp_mask);
3924     set_mask = TRUE;
3925   }
3926
3927   /* Get channel entry */
3928   channel = silc_idlist_find_channel_by_id(server->local_list, 
3929                                            channel_id, NULL);
3930   if (!channel) {
3931     channel = silc_idlist_find_channel_by_id(server->global_list, 
3932                                              channel_id, NULL);
3933     if (!channel) {
3934       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3935                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3936                                             0);
3937       goto out;
3938     }
3939   }
3940
3941   /* Check whether this client is on the channel */
3942   if (!silc_server_client_on_channel(client, channel, &chl)) {
3943     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3945     goto out;
3946   }
3947
3948   /* Check that client has rights to change any requested channel modes */
3949   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
3950                                                   mode_mask)) {
3951     silc_server_command_send_status_reply(
3952                              cmd, SILC_COMMAND_CMODE,
3953                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
3954                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3955                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3956     goto out;
3957   }
3958
3959   /* If mode mask was not sent as argument then merely return the current
3960      mode mask to the sender. */
3961   if (!set_mask) {
3962     unsigned char m[4];
3963     SILC_PUT32_MSB(channel->mode, m);
3964     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3965                                                   SILC_STATUS_OK, 0, ident, 2,
3966                                                   2, tmp_id, tmp_len2,
3967                                                   3, m, sizeof(m));
3968     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3969                             packet->data, packet->len, FALSE);
3970     silc_buffer_free(packet);
3971     goto out;
3972   }
3973
3974   /*
3975    * Check the modes. Modes that requires nothing special operation are
3976    * not checked here.
3977    */
3978
3979   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3980     /* Channel uses private keys to protect traffic. Client(s) has set the
3981        key locally they want to use, server does not know that key. */
3982     /* Nothing interesting to do here */
3983   } else {
3984     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3985       /* The mode is removed and we need to generate and distribute
3986          new channel key. Clients are not using private channel keys
3987          anymore after this. */
3988       
3989       /* Re-generate channel key */
3990       if (!silc_server_create_channel_key(server, channel, 0))
3991         goto out;
3992         
3993       /* Send the channel key. This sends it to our local clients and if
3994          we are normal server to our router as well. */
3995       silc_server_send_channel_key(server, NULL, channel, 
3996                                    server->server_type == SILC_ROUTER ? 
3997                                    FALSE : !server->standalone);
3998         
3999       cipher = channel->channel_key->cipher->name;
4000       hmac = (char *)silc_hmac_get_name(channel->hmac);
4001     }
4002   }
4003
4004   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4005     /* User limit is set on channel */
4006     SilcUInt32 user_limit;
4007       
4008     /* Get user limit */
4009     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4010     if (!tmp) {
4011       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4012         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4014         goto out;
4015       }
4016     } else {
4017       SILC_GET32_MSB(user_limit, tmp);
4018       channel->user_limit = user_limit;
4019     }
4020   } else {
4021     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4022       /* User limit mode is unset. Remove user limit */
4023       channel->user_limit = 0;
4024   }
4025
4026   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4027     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4028       /* Passphrase has been set to channel */
4029       
4030       /* Get the passphrase */
4031       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4032       if (!tmp) {
4033         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4034                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4035         goto out;
4036       }
4037
4038       /* Save the passphrase */
4039       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4040     }
4041   } else {
4042     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4043       /* Passphrase mode is unset. remove the passphrase */
4044       silc_free(channel->passphrase);
4045       channel->passphrase = NULL;
4046     }
4047   }
4048
4049   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4050     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4051       /* Cipher to use protect the traffic */
4052       SilcCipher newkey, oldkey;
4053
4054       /* Get cipher */
4055       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4056       if (!cipher) {
4057         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4058                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4059         goto out;
4060       }
4061
4062       /* Delete old cipher and allocate the new one */
4063       if (!silc_cipher_alloc(cipher, &newkey)) {
4064         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4065                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4066         goto out;
4067       }
4068
4069       oldkey = channel->channel_key;
4070       channel->channel_key = newkey;
4071
4072       /* Re-generate channel key */
4073       if (!silc_server_create_channel_key(server, channel, 0)) {
4074         /* We don't have new key, revert to old one */
4075         channel->channel_key = oldkey;
4076         goto out;
4077       }
4078
4079       /* Remove old channel key for good */
4080       silc_cipher_free(oldkey);
4081
4082       /* Send the channel key. This sends it to our local clients and if
4083          we are normal server to our router as well. */
4084       silc_server_send_channel_key(server, NULL, channel, 
4085                                    server->server_type == SILC_ROUTER ? 
4086                                    FALSE : !server->standalone);
4087     }
4088   } else {
4089     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4090       /* Cipher mode is unset. Remove the cipher and revert back to 
4091          default cipher */
4092       SilcCipher newkey, oldkey;
4093       cipher = channel->cipher;
4094
4095       /* Delete old cipher and allocate default one */
4096       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4097         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4098                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4099         goto out;
4100       }
4101
4102       oldkey = channel->channel_key;
4103       channel->channel_key = newkey;
4104
4105       /* Re-generate channel key */
4106       if (!silc_server_create_channel_key(server, channel, 0)) {
4107         /* We don't have new key, revert to old one */
4108         channel->channel_key = oldkey;
4109         goto out;
4110       }
4111       
4112       /* Remove old channel key for good */
4113       silc_cipher_free(oldkey);
4114
4115       /* Send the channel key. This sends it to our local clients and if
4116          we are normal server to our router as well. */
4117       silc_server_send_channel_key(server, NULL, channel, 
4118                                    server->server_type == SILC_ROUTER ? 
4119                                    FALSE : !server->standalone);
4120     }
4121   }
4122
4123   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4124     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4125       /* HMAC to use protect the traffic */
4126       unsigned char hash[32];
4127       SilcHmac newhmac;
4128
4129       /* Get hmac */
4130       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4131       if (!hmac) {
4132         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4133                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4134         goto out;
4135       }
4136
4137       /* Delete old hmac and allocate the new one */
4138       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4139         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4140                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4141         goto out;
4142       }
4143
4144       silc_hmac_free(channel->hmac);
4145       channel->hmac = newhmac;
4146
4147       /* Set the HMAC key out of current channel key. The client must do
4148          this locally. */
4149       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4150                      channel->key_len / 8, hash);
4151       silc_hmac_set_key(channel->hmac, hash, 
4152                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4153       memset(hash, 0, sizeof(hash));
4154     }
4155   } else {
4156     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4157       /* Hmac mode is unset. Remove the hmac and revert back to 
4158          default hmac */
4159       SilcHmac newhmac;
4160       unsigned char hash[32];
4161       hmac = channel->hmac_name;
4162
4163       /* Delete old hmac and allocate default one */
4164       silc_hmac_free(channel->hmac);
4165       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4166         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4167                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4168         goto out;
4169       }
4170
4171       silc_hmac_free(channel->hmac);
4172       channel->hmac = newhmac;
4173
4174       /* Set the HMAC key out of current channel key. The client must do
4175          this locally. */
4176       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4177                      channel->key_len / 8, 
4178                      hash);
4179       silc_hmac_set_key(channel->hmac, hash, 
4180                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4181       memset(hash, 0, sizeof(hash));
4182     }
4183   }
4184
4185   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4186     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4187       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4188         /* Set the founder authentication */
4189         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4190         if (!tmp) {
4191           silc_server_command_send_status_reply(
4192                                      cmd, SILC_COMMAND_CMODE,
4193                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4194           goto out;
4195         }
4196
4197         /* Verify the payload before setting the mode */
4198         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
4199                                    idata->public_key, 0, server->sha1hash,
4200                                    client->id, SILC_ID_CLIENT)) {
4201           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4202                                                 SILC_STATUS_ERR_AUTH_FAILED,
4203                                                 0);
4204           goto out;
4205         }
4206
4207         /* Save the public key */
4208         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4209         founder_key = channel->founder_key;
4210         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4211       }
4212     }
4213   } else {
4214     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4215       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4216         if (channel->founder_key)
4217           silc_pkcs_public_key_free(channel->founder_key);
4218         channel->founder_key = NULL;
4219       }
4220     }
4221   }
4222
4223   /* Finally, set the mode */
4224   channel->mode = mode_mask;
4225
4226   /* Send CMODE_CHANGE notify. */
4227   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4228   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4229                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4230                                      cidp->data, cidp->len, 
4231                                      tmp_mask, 4,
4232                                      cipher, cipher ? strlen(cipher) : 0,
4233                                      hmac, hmac ? strlen(hmac) : 0,
4234                                      passphrase, passphrase ? 
4235                                      strlen(passphrase) : 0,
4236                                      fkey, fkey_len);
4237
4238   /* Set CMODE notify type to network */
4239   if (!server->standalone)
4240     silc_server_send_notify_cmode(server, server->router->connection,
4241                                   server->server_type == SILC_ROUTER ? 
4242                                   TRUE : FALSE, channel,
4243                                   mode_mask, client->id, SILC_ID_CLIENT,
4244                                   cipher, hmac, passphrase, founder_key);
4245
4246   /* Send command reply to sender */
4247   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4248                                                 SILC_STATUS_OK, 0, ident, 2,
4249                                                 2, tmp_id, tmp_len2,
4250                                                 3, tmp_mask, 4);
4251   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4252                           packet->data, packet->len, FALSE);
4253     
4254   silc_buffer_free(packet);
4255   silc_buffer_free(cidp);
4256
4257  out:
4258   silc_free(fkey);
4259   silc_free(channel_id);
4260   silc_server_command_free(cmd);
4261 }
4262
4263 /* Server side of CUMODE command. Changes client's mode on a channel. */
4264
4265 SILC_SERVER_CMD_FUNC(cumode)
4266 {
4267   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4268   SilcServer server = cmd->server;
4269   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4270   SilcIDListData idata = (SilcIDListData)client;
4271   SilcChannelID *channel_id;
4272   SilcClientID *client_id;
4273   SilcChannelEntry channel;
4274   SilcClientEntry target_client;
4275   SilcChannelClientEntry chl;
4276   SilcBuffer packet, idp;
4277   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4278   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4279   int notify = FALSE;
4280   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4281   SilcPublicKey founder_key = NULL;
4282   unsigned char *fkey = NULL;
4283   SilcUInt32 fkey_len = 0;
4284
4285   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4286
4287   /* Get Channel ID */
4288   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4289   if (!tmp_ch_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   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4295   if (!channel_id) {
4296     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4297                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4298     goto out;
4299   }
4300
4301   /* Get channel entry */
4302   channel = silc_idlist_find_channel_by_id(server->local_list, 
4303                                            channel_id, NULL);
4304   if (!channel) {
4305     channel = silc_idlist_find_channel_by_id(server->global_list, 
4306                                              channel_id, NULL);
4307     if (!channel) {
4308       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4310                                             0);
4311       goto out;
4312     }
4313   }
4314
4315   /* Check whether sender is on the channel */
4316   if (!silc_server_client_on_channel(client, channel, &chl)) {
4317     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4318                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4319     goto out;
4320   }
4321   sender_mask = chl->mode;
4322   
4323   /* Get the target client's channel mode mask */
4324   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4325   if (!tmp_mask) {
4326     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4327                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4328                                           0);
4329     goto out;
4330   }
4331   SILC_GET32_MSB(target_mask, tmp_mask);
4332
4333   /* Get target Client ID */
4334   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4335   if (!tmp_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   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4341   if (!client_id) {
4342     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4343                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4344     goto out;
4345   }
4346
4347   /* Get target client's entry */
4348   target_client = silc_idlist_find_client_by_id(server->local_list, 
4349                                                 client_id, TRUE, NULL);
4350   if (!target_client) {
4351     target_client = silc_idlist_find_client_by_id(server->global_list, 
4352                                                   client_id, TRUE, NULL);
4353   }
4354
4355   if (target_client != client &&
4356       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4357       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4358     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4359                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4360     goto out;
4361   }
4362
4363   /* Check whether target client is on the channel */
4364   if (target_client != client) {
4365     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4366       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4367                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4368       goto out;
4369     }
4370   }
4371
4372   /* 
4373    * Change the mode 
4374    */
4375
4376   /* If the target client is founder, no one else can change their mode
4377      but themselves. */
4378   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4379     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4380                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4381                                           0);
4382     goto out;
4383   }
4384
4385   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4386     if (target_client != client) {
4387       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4388                                             SILC_STATUS_ERR_NOT_YOU, 0);
4389       goto out;
4390     }
4391
4392     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4393       /* The client tries to claim the founder rights. */
4394       unsigned char *tmp_auth;
4395       SilcUInt32 tmp_auth_len;
4396
4397       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4398           !channel->founder_key || !idata->public_key ||
4399           !silc_pkcs_public_key_compare(channel->founder_key, 
4400                                         idata->public_key)) {
4401         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4402                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4403         goto out;
4404       }
4405
4406       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4407       if (!tmp_auth) {
4408         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4409                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4410         goto out;
4411       }
4412
4413       /* Verify the authentication payload */
4414       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4415                                  channel->founder_key, 0, server->sha1hash,
4416                                  client->id, SILC_ID_CLIENT)) {
4417         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4418                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4419         goto out;
4420       }
4421
4422       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4423       notify = TRUE;
4424       founder_key = channel->founder_key;
4425       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4426     }
4427   } else {
4428     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4429       if (target_client == client) {
4430         /* Remove channel founder rights from itself */
4431         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4432         notify = TRUE;
4433       } else {
4434         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4435                                               SILC_STATUS_ERR_NOT_YOU, 0);
4436         goto out;
4437       }
4438     }
4439   }
4440
4441   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4442     /* Promote to operator */
4443     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4444       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4445           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4446         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4447                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4448                                               0);
4449         goto out;
4450       }
4451
4452       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4453       notify = TRUE;
4454     }
4455   } else {
4456     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4457       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4458           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4459         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4460                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4461                                               0);
4462         goto out;
4463       }
4464
4465       /* Demote to normal user */
4466       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4467       notify = TRUE;
4468     }
4469   }
4470
4471   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4472     if (target_client != client) {
4473       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4474                                             SILC_STATUS_ERR_NOT_YOU, 0);
4475       goto out;
4476     }
4477
4478     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4479       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4480       notify = TRUE;
4481     }
4482   } else {
4483     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4484       if (target_client != client) {
4485         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4486                                               SILC_STATUS_ERR_NOT_YOU, 0);
4487         goto out;
4488       }
4489
4490       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4491       notify = TRUE;
4492     }
4493   }
4494
4495   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4496     if (target_client != client) {
4497       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4498                                             SILC_STATUS_ERR_NOT_YOU, 0);
4499       goto out;
4500     }
4501
4502     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4503       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4504       notify = TRUE;
4505     }
4506   } else {
4507     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4508       if (target_client != client) {
4509         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4510                                               SILC_STATUS_ERR_NOT_YOU, 0);
4511         goto out;
4512       }
4513
4514       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4515       notify = TRUE;
4516     }
4517   }
4518
4519   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4520     if (target_client != client) {
4521       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4522                                             SILC_STATUS_ERR_NOT_YOU, 0);
4523       goto out;
4524     }
4525
4526     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4527       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4528       notify = TRUE;
4529     }
4530   } else {
4531     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4532       if (target_client != client) {
4533         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4534                                               SILC_STATUS_ERR_NOT_YOU, 0);
4535         goto out;
4536       }
4537
4538       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4539       notify = TRUE;
4540     }
4541   }
4542
4543   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4544   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4545
4546   /* Send notify to channel, notify only if mode was actually changed. */
4547   if (notify) {
4548     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4549                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4550                                        idp->data, idp->len,
4551                                        tmp_mask, 4, 
4552                                        tmp_id, tmp_len,
4553                                        fkey, fkey_len);
4554
4555     /* Set CUMODE notify type to network */
4556     if (!server->standalone)
4557       silc_server_send_notify_cumode(server, server->router->connection,
4558                                      server->server_type == SILC_ROUTER ? 
4559                                      TRUE : FALSE, channel,
4560                                      target_mask, client->id, 
4561                                      SILC_ID_CLIENT,
4562                                      target_client->id, founder_key);
4563   }
4564
4565   /* Send command reply to sender */
4566   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4567                                                 SILC_STATUS_OK, 0, ident, 3,
4568                                                 2, tmp_mask, 4,
4569                                                 3, tmp_ch_id, tmp_ch_len,
4570                                                 4, tmp_id, tmp_len);
4571   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4572                           packet->data, packet->len, FALSE);
4573     
4574   silc_buffer_free(packet);
4575   silc_free(channel_id);
4576   silc_free(client_id);
4577   silc_buffer_free(idp);
4578
4579  out:
4580   silc_free(fkey);
4581   silc_server_command_free(cmd);
4582 }
4583
4584 /* Server side of KICK command. Kicks client out of channel. */
4585
4586 SILC_SERVER_CMD_FUNC(kick)
4587 {
4588   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4589   SilcServer server = cmd->server;
4590   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4591   SilcClientEntry target_client;
4592   SilcChannelID *channel_id;
4593   SilcClientID *client_id;
4594   SilcChannelEntry channel;
4595   SilcChannelClientEntry chl;
4596   SilcBuffer idp;
4597   SilcUInt32 tmp_len, target_idp_len;
4598   unsigned char *tmp, *comment, *target_idp;
4599
4600   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4601
4602   /* Get Channel ID */
4603   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4604   if (!tmp) {
4605     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4606                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4607     goto out;
4608   }
4609   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4610   if (!channel_id) {
4611     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4612                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4613     goto out;
4614   }
4615
4616   /* Get channel entry */
4617   channel = silc_idlist_find_channel_by_id(server->local_list, 
4618                                            channel_id, NULL);
4619   if (!channel) {
4620     channel = silc_idlist_find_channel_by_id(server->local_list, 
4621                                              channel_id, NULL);
4622     if (!channel) {
4623       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4624                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4625                                             0);
4626       goto out;
4627     }
4628   }
4629
4630   /* Check whether sender is on the channel */
4631   if (!silc_server_client_on_channel(client, channel, &chl)) {
4632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4633                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4634     goto out;
4635   }
4636
4637   /* Check that the kicker is channel operator or channel founder */
4638   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4639       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4640     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4641                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4642     goto out;
4643   }
4644   
4645   /* Get target Client ID */
4646   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4647   if (!target_idp) {
4648     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4649                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4650     goto out;
4651   }
4652   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4653   if (!client_id) {
4654     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4655                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4656     goto out;
4657   }
4658
4659   /* Get target client's entry */
4660   target_client = silc_idlist_find_client_by_id(server->local_list, 
4661                                                 client_id, TRUE, NULL);
4662   if (!target_client) {
4663     target_client = silc_idlist_find_client_by_id(server->global_list, 
4664                                                   client_id, TRUE, NULL);
4665   }
4666
4667   /* Check whether target client is on the channel */
4668   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4669     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4670                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4671                                           0);
4672     goto out;
4673   }
4674
4675   /* Check that the target client is not channel founder. Channel founder
4676      cannot be kicked from the channel. */
4677   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4678     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4679                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4680                                           0);
4681     goto out;
4682   }
4683   
4684   /* Get comment */
4685   tmp_len = 0;
4686   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4687   if (tmp_len > 128)
4688     comment = NULL;
4689
4690   /* Send command reply to sender */
4691   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4692                                         SILC_STATUS_OK, 0);
4693
4694   /* Send KICKED notify to local clients on the channel */
4695   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4696   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4697                                      SILC_NOTIFY_TYPE_KICKED, 3,
4698                                      target_idp, target_idp_len,
4699                                      comment, comment ? strlen(comment) : 0,
4700                                      idp->data, idp->len);
4701   silc_buffer_free(idp);
4702
4703   /* Remove the client from the channel. If the channel does not exist
4704      after removing the client then the client kicked itself off the channel
4705      and we don't have to send anything after that. */
4706   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4707                                            target_client, FALSE))
4708     goto out;
4709
4710   /* Send KICKED notify to primary route */
4711   if (!server->standalone)
4712     silc_server_send_notify_kicked(server, server->router->connection,
4713                                    server->server_type == SILC_ROUTER ?
4714                                    TRUE : FALSE, channel,
4715                                    target_client->id, client->id, comment);
4716
4717   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4718     /* Re-generate channel key */
4719     if (!silc_server_create_channel_key(server, channel, 0))
4720       goto out;
4721     
4722     /* Send the channel key to the channel. The key of course is not sent
4723        to the client who was kicked off the channel. */
4724     silc_server_send_channel_key(server, target_client->connection, channel, 
4725                                  server->server_type == SILC_ROUTER ? 
4726                                  FALSE : !server->standalone);
4727   }
4728
4729  out:
4730   silc_server_command_free(cmd);
4731 }
4732
4733 /* Server side of OPER command. Client uses this comand to obtain server
4734    operator privileges to this server/router. */
4735
4736 SILC_SERVER_CMD_FUNC(oper)
4737 {
4738   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4739   SilcServer server = cmd->server;
4740   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4741   unsigned char *username, *auth;
4742   SilcUInt32 tmp_len;
4743   SilcServerConfigAdmin *admin;
4744   SilcIDListData idata = (SilcIDListData)client;
4745   bool result = FALSE;
4746   SilcPublicKey cached_key;
4747
4748   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4749
4750   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4751     goto out;
4752
4753   /* Get the username */
4754   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4755   if (!username) {
4756     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4757                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4758                                           0);
4759     goto out;
4760   }
4761
4762   /* Get the admin configuration */
4763   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4764                                         username, client->nickname);
4765   if (!admin) {
4766     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4767                                           username, client->nickname);
4768     if (!admin) {
4769       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4770                                             SILC_STATUS_ERR_AUTH_FAILED,
4771                                             0);
4772       goto out;
4773     }
4774   }
4775
4776   /* Get the authentication payload */
4777   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4778   if (!auth) {
4779     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4780                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4781                                           0);
4782     goto out;
4783   }
4784
4785   /* Verify the authentication data. If both passphrase and public key
4786      is set then try both of them. */
4787   if (admin->passphrase)
4788     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4789                                    admin->passphrase, admin->passphrase_len,
4790                                    idata->hash, client->id, SILC_ID_CLIENT);
4791   if (!result && admin->publickeys) {
4792     cached_key = silc_server_get_public_key(server, admin->publickeys);
4793     if (!cached_key)
4794       goto out;
4795     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4796                                    cached_key, 0, idata->hash, 
4797                                    client->id, SILC_ID_CLIENT);
4798   }
4799   if (!result) {
4800     /* Authentication failed */
4801     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4802                                           SILC_STATUS_ERR_AUTH_FAILED,
4803                                           0);
4804     goto out;
4805   }
4806
4807   /* Client is now server operator */
4808   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4809
4810   /* Update statistics */
4811   if (client->connection)
4812     server->stat.my_server_ops++;
4813   if (server->server_type == SILC_ROUTER)
4814     server->stat.server_ops++;
4815
4816   /* Send UMODE change to primary router */
4817   if (!server->standalone)
4818     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4819                                   client->id, client->mode);
4820
4821   /* Check if anyone is watching this nickname */
4822   if (server->server_type == SILC_ROUTER)
4823     silc_server_check_watcher_list(server, client, NULL,
4824                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4825
4826   /* Send reply to the sender */
4827   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4828                                         SILC_STATUS_OK, 0);
4829
4830  out:
4831   silc_server_command_free(cmd);
4832 }
4833
4834 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4835 {
4836   QuitInternal q = (QuitInternal)context;
4837   SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4838
4839   /* If there is pending outgoing data for the client then purge it
4840      to the network before closing connection. */
4841   silc_server_packet_queue_purge(q->server, q->sock);
4842
4843   /* Close the connection on our side */
4844   client->router = NULL;
4845   client->connection = NULL;
4846   q->sock->user_data = NULL;
4847   silc_server_close_connection(q->server, q->sock);
4848
4849   silc_free(q);
4850 }
4851
4852 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4853 {
4854   QuitInternal q = (QuitInternal)context;
4855   SilcClientEntry client = (SilcClientEntry)q->sock;
4856
4857   SILC_LOG_DEBUG(("Start"));
4858
4859   if (client->mode & SILC_UMODE_DETACHED)
4860     silc_server_free_client_data(q->server, NULL, client, TRUE,
4861                                  "Detach timeout");
4862   silc_free(q);
4863 }
4864
4865 /* Server side of DETACH command.  Detached the client from the network
4866    by closing the connection but preserving the session. */
4867
4868 SILC_SERVER_CMD_FUNC(detach)
4869 {
4870   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4871   SilcServer server = cmd->server;
4872   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4873   QuitInternal q;
4874
4875   if (server->config->detach_disabled) {
4876     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4877                                           SILC_STATUS_ERR_UNKNOWN_COMMAND,
4878                                           0);
4879     goto out;
4880   }
4881
4882   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4883     goto out;
4884
4885   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4886
4887   /* Send the user mode notify to notify that client is detached */
4888   client->mode |= SILC_UMODE_DETACHED;
4889   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4890   client->last_command = 0;
4891   client->fast_command = 0;
4892   if (!server->standalone)
4893     silc_server_send_notify_umode(server, server->router->connection,
4894                                   server->server_type == SILC_SERVER ?
4895                                   FALSE : TRUE, client->id, client->mode);
4896
4897   /* Check if anyone is watching this nickname */
4898   if (server->server_type == SILC_ROUTER)
4899     silc_server_check_watcher_list(server, client, NULL,
4900                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4901
4902   q = silc_calloc(1, sizeof(*q));
4903   q->server = server;
4904   q->sock = cmd->sock;
4905   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4906                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4907
4908   if (server->config->detach_timeout) {
4909     q = silc_calloc(1, sizeof(*q));
4910     q->server = server;
4911     q->sock = (void *)client;
4912     silc_schedule_task_add(server->schedule, 0, 
4913                            silc_server_command_detach_timeout,
4914                            q, server->config->detach_timeout * 60,
4915                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4916   }
4917
4918   /* Send reply to the sender */
4919   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4920                                         SILC_STATUS_OK, 0);
4921
4922  out:
4923   silc_server_command_free(cmd);
4924 }
4925
4926 /* Server side of WATCH command. */
4927
4928 SILC_SERVER_CMD_FUNC(watch)
4929 {
4930   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4931   SilcServer server = cmd->server;
4932   char *add_nick, *del_nick;
4933   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4934   char nick[128 + 1];
4935   unsigned char hash[16], *tmp;
4936   SilcClientEntry client;
4937   SilcClientID *client_id = NULL;
4938
4939   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4940
4941   if (server->server_type == SILC_SERVER && !server->standalone) {
4942     if (!cmd->pending) {
4943       /* Send the command to router */
4944       SilcBuffer tmpbuf;
4945       SilcUInt16 old_ident;
4946
4947       old_ident = silc_command_get_ident(cmd->payload);
4948       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4949       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4950
4951       silc_server_packet_send(server, server->router->connection,
4952                               SILC_PACKET_COMMAND, cmd->packet->flags,
4953                               tmpbuf->data, tmpbuf->len, TRUE);
4954
4955       /* Reprocess this packet after received reply from router */
4956       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4957                                   silc_command_get_ident(cmd->payload),
4958                                   silc_server_command_watch,
4959                                   silc_server_command_dup(cmd));
4960       cmd->pending = TRUE;
4961       silc_command_set_ident(cmd->payload, old_ident);
4962       silc_buffer_free(tmpbuf);
4963     } else if (context2) {
4964       /* Received reply from router, just send same data to the client. */
4965       SilcServerCommandReplyContext reply = context2;
4966       SilcStatus status;
4967       silc_command_get_status(reply->payload, &status, NULL);
4968       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4969                                             0);
4970     }
4971
4972     goto out;
4973   }
4974
4975   /* We are router and keep the watch list for local cell */
4976
4977   /* Get the client ID */
4978   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4979   if (!tmp) {
4980     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4981                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4982                                           0);
4983     goto out;
4984   }
4985   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4986   if (!client_id) {
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   /* Get the client entry which must be in local list */
4994   client = silc_idlist_find_client_by_id(server->local_list, 
4995                                          client_id, TRUE, NULL);
4996   if (!client) {
4997     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4998                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4999                                           0);
5000     goto out;
5001   }
5002
5003   /* Take nickname */
5004   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5005   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5006   if (!add_nick && !del_nick) {
5007     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5008                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5009                                           0);
5010     goto out;
5011   }
5012
5013   if (add_nick && add_nick_len > 128)
5014     add_nick[128] = '\0';
5015   if (del_nick && del_nick_len > 128)
5016     del_nick[128] = '\0';
5017
5018   memset(nick, 0, sizeof(nick));
5019
5020   /* Add new nickname to be watched in our cell */
5021   if (add_nick) {
5022     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5023       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5024                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5025       goto out;
5026     }
5027
5028     /* Hash the nick, we have the hash saved, not nicks because we can
5029        do one to one mapping to the nick from Client ID hash this way. */
5030     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5031     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5032
5033     /* Check whether this client is already watching this nickname */
5034     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
5035                                         client, NULL)) {
5036       /* Nickname is alredy being watched for this client */
5037       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5038                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
5039                                             0);
5040       goto out;
5041     }
5042
5043     /* Get the nickname from the watcher list and use the same key in
5044        new entries as well.  If key doesn't exist then create it. */
5045     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5046       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5047
5048     /* Add the client to the watcher list with the specified nickname hash. */
5049     silc_hash_table_add(server->watcher_list, tmp, client);
5050   }
5051
5052   /* Delete nickname from watch list */
5053   if (del_nick) {
5054     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5055       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5056                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5057       goto out;
5058     }
5059
5060     /* Hash the nick, we have the hash saved, not nicks because we can
5061        do one to one mapping to the nick from Client ID hash this way. */
5062     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5063     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5064
5065     /* Check that this client is watching for this nickname */
5066     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
5067                                          client, (void **)&tmp)) {
5068       /* Nickname is alredy being watched for this client */
5069       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5070                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5071       goto out;
5072     }
5073
5074     /* Delete the nickname from the watcher list. */
5075     silc_hash_table_del_by_context(server->watcher_list, hash, client);
5076
5077     /* Now check whether there still exists entries with this key, if not
5078        then free the key to not leak memory. */
5079     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5080       silc_free(tmp);
5081   }
5082
5083   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5084                                         SILC_STATUS_OK, 0);
5085
5086  out:
5087   silc_free(client_id);
5088   silc_server_command_free(cmd);
5089 }
5090
5091 /* Server side of SILCOPER command. Client uses this comand to obtain router
5092    operator privileges to this router. */
5093
5094 SILC_SERVER_CMD_FUNC(silcoper)
5095 {
5096   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5097   SilcServer server = cmd->server;
5098   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5099   unsigned char *username, *auth;
5100   SilcUInt32 tmp_len;
5101   SilcServerConfigAdmin *admin;
5102   SilcIDListData idata = (SilcIDListData)client;
5103   bool result = FALSE;
5104   SilcPublicKey cached_key;
5105
5106   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5107
5108   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5109     goto out;
5110
5111   if (server->server_type != SILC_ROUTER) {
5112     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5113                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5114     goto out;
5115   }
5116
5117   /* Get the username */
5118   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5119   if (!username) {
5120     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5121                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5122                                           0);
5123     goto out;
5124   }
5125
5126   /* Get the admin configuration */
5127   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5128                                         username, client->nickname);
5129   if (!admin) {
5130     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5131                                           username, client->nickname);
5132     if (!admin) {
5133       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5134                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
5135       goto out;
5136     }
5137   }
5138
5139   /* Get the authentication payload */
5140   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5141   if (!auth) {
5142     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5143                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5144                                           0);
5145     goto out;
5146   }
5147
5148   /* Verify the authentication data. If both passphrase and public key
5149      is set then try both of them. */
5150   if (admin->passphrase)
5151     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5152                                    admin->passphrase, admin->passphrase_len,
5153                                    idata->hash, client->id, SILC_ID_CLIENT);
5154   if (!result && admin->publickeys) {
5155     cached_key = silc_server_get_public_key(server, admin->publickeys);
5156     if (!cached_key)
5157       goto out;
5158     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5159                                    cached_key, 0, idata->hash, 
5160                                    client->id, SILC_ID_CLIENT);
5161   }
5162   if (!result) {
5163     /* Authentication failed */
5164     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5165                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5166     goto out;
5167   }
5168
5169   /* Client is now router operator */
5170   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5171
5172   /* Update statistics */
5173   if (client->connection)
5174     server->stat.my_router_ops++;
5175   if (server->server_type == SILC_ROUTER)
5176     server->stat.router_ops++;
5177
5178   /* Send UMODE change to primary router */
5179   if (!server->standalone)
5180     silc_server_send_notify_umode(server, server->router->connection, TRUE,
5181                                   client->id, client->mode);
5182
5183   /* Check if anyone is watching this nickname */
5184   if (server->server_type == SILC_ROUTER)
5185     silc_server_check_watcher_list(server, client, NULL,
5186                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5187
5188   /* Send reply to the sender */
5189   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5190                                         SILC_STATUS_OK, 0);
5191
5192  out:
5193   silc_server_command_free(cmd);
5194 }
5195
5196 /* Server side of command BAN. This is used to manage the ban list of the
5197    channel. To add clients and remove clients from the ban list. */
5198
5199 SILC_SERVER_CMD_FUNC(ban)
5200 {
5201   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5202   SilcServer server = cmd->server;
5203   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5204   SilcBuffer packet;
5205   SilcChannelEntry channel;
5206   SilcChannelClientEntry chl;
5207   SilcChannelID *channel_id = NULL;
5208   unsigned char *id, *add, *del;
5209   SilcUInt32 id_len, tmp_len;
5210   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5211
5212   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5213     goto out;
5214
5215   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5216
5217   /* Get Channel ID */
5218   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5219   if (id) {
5220     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5221     if (!channel_id) {
5222       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5223                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5224       goto out;
5225     }
5226   }
5227
5228   /* Get channel entry. The server must know about the channel since the
5229      client is expected to be on the channel. */
5230   channel = silc_idlist_find_channel_by_id(server->local_list, 
5231                                            channel_id, NULL);
5232   if (!channel) {
5233     channel = silc_idlist_find_channel_by_id(server->global_list, 
5234                                              channel_id, NULL);
5235     if (!channel) {
5236       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5237                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5238                                             0);
5239       goto out;
5240     }
5241   }
5242
5243   /* Check whether this client is on the channel */
5244   if (!silc_server_client_on_channel(client, channel, &chl)) {
5245     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5246                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5247     goto out;
5248   }
5249
5250   /* The client must be at least channel operator. */
5251   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5253                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5254     goto out;
5255   }
5256
5257   /* Get the new ban and add it to the ban list */
5258   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5259   if (add) {
5260     if (!channel->ban_list)
5261       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5262     else
5263       channel->ban_list = silc_realloc(channel->ban_list, 
5264                                        sizeof(*channel->ban_list) * 
5265                                        (tmp_len + 
5266                                         strlen(channel->ban_list) + 2));
5267     if (add[tmp_len - 1] == ',')
5268       add[tmp_len - 1] = '\0';
5269
5270     strncat(channel->ban_list, add, tmp_len);
5271     strncat(channel->ban_list, ",", 1);
5272   }
5273
5274   /* Get the ban to be removed and remove it from the list */
5275   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5276   if (del && channel->ban_list) {
5277     char *start, *end, *n;
5278
5279     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5280       silc_free(channel->ban_list);
5281       channel->ban_list = NULL;
5282     } else {
5283       start = strstr(channel->ban_list, del);
5284       if (start && strlen(start) >= tmp_len) {
5285         end = start + tmp_len;
5286         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5287         strncat(n, channel->ban_list, start - channel->ban_list);
5288         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
5289                              end) - 1);
5290         silc_free(channel->ban_list);
5291         channel->ban_list = n;
5292       }
5293     }
5294   }
5295
5296   /* Send the BAN notify type to our primary router. */
5297   if (!server->standalone && (add || del))
5298     silc_server_send_notify_ban(server, server->router->connection,
5299                                 server->server_type == SILC_ROUTER ?
5300                                 TRUE : FALSE, channel, add, del);
5301
5302   /* Send the reply back to the client */
5303   packet = 
5304     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5305                                          SILC_STATUS_OK, 0, ident, 2,
5306                                          2, id, id_len,
5307                                          3, channel->ban_list, 
5308                                          channel->ban_list ? 
5309                                          strlen(channel->ban_list) -1 : 0);
5310   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5311                           packet->data, packet->len, FALSE);
5312     
5313   silc_buffer_free(packet);
5314
5315  out:
5316   silc_free(channel_id);
5317   silc_server_command_free(cmd);
5318 }
5319
5320 /* Server side command of LEAVE. Removes client from a channel. */
5321
5322 SILC_SERVER_CMD_FUNC(leave)
5323 {
5324   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5325   SilcServer server = cmd->server;
5326   SilcSocketConnection sock = cmd->sock;
5327   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5328   SilcChannelID *id = NULL;
5329   SilcChannelEntry channel;
5330   SilcUInt32 len;
5331   unsigned char *tmp;
5332
5333   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5334
5335   /* Get Channel ID */
5336   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5337   if (!tmp) {
5338     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5339                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5340     goto out;
5341   }
5342   id = silc_id_payload_parse_id(tmp, len, NULL);
5343   if (!id) {
5344     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5345                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5346     goto out;
5347   }
5348
5349   /* Get channel entry */
5350   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5351   if (!channel) {
5352     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5353     if (!channel) {
5354       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5355                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5356                                             0);
5357       goto out;
5358     }
5359   }
5360
5361   /* Check whether this client is on the channel */
5362   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5363     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5364                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5365     goto out;
5366   }
5367
5368   /* Notify routers that they should remove this client from their list
5369      of clients on the channel. Send LEAVE notify type. */
5370   if (!server->standalone)
5371     silc_server_send_notify_leave(server, server->router->connection,
5372                                   server->server_type == SILC_ROUTER ?
5373                                   TRUE : FALSE, channel, id_entry->id);
5374
5375   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5376                                        SILC_STATUS_OK, 0, 2, tmp, len);
5377
5378   /* Remove client from channel */
5379   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5380                                            TRUE))
5381     /* If the channel does not exist anymore we won't send anything */
5382     goto out;
5383
5384   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5385     /* Re-generate channel key */
5386     if (!silc_server_create_channel_key(server, channel, 0))
5387       goto out;
5388
5389     /* Send the channel key */
5390     silc_server_send_channel_key(server, NULL, channel, 
5391                                  server->server_type == SILC_ROUTER ? 
5392                                  FALSE : !server->standalone);
5393   }
5394
5395  out:
5396   silc_free(id);
5397   silc_server_command_free(cmd);
5398 }
5399
5400 /* Server side of command USERS. Resolves clients and their USERS currently
5401    joined on the requested channel. The list of Client ID's and their modes
5402    on the channel is sent back. */
5403
5404 SILC_SERVER_CMD_FUNC(users)
5405 {
5406   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5407   SilcServer server = cmd->server;
5408   SilcChannelEntry channel;
5409   SilcChannelID *id = NULL;
5410   SilcBuffer packet, idp;
5411   unsigned char *channel_id;
5412   SilcUInt32 channel_id_len;
5413   SilcBuffer client_id_list;
5414   SilcBuffer client_mode_list;
5415   unsigned char lc[4];
5416   SilcUInt32 list_count = 0;
5417   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5418   char *channel_name;
5419
5420   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5421
5422   /* Get Channel ID */
5423   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5424
5425   /* Get channel name */
5426   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5427
5428   if (!channel_id && !channel_name) {
5429     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5430                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5431     goto out;
5432   }
5433
5434   if (channel_id) {
5435     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5436     if (!id) {
5437       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5438                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5439       goto out;
5440     }
5441   }
5442
5443   /* If we are server and we don't know about this channel we will send
5444      the command to our router. If we know about the channel then we also
5445      have the list of users already. */
5446   if (id)
5447     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5448   else
5449     channel = silc_idlist_find_channel_by_name(server->local_list, 
5450                                                channel_name, NULL);
5451
5452   if (!channel || channel->disabled || !channel->users_resolved) {
5453     if (server->server_type != SILC_ROUTER && !server->standalone &&
5454         !cmd->pending) {
5455       SilcBuffer tmpbuf;
5456       
5457       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5458       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5459       
5460       /* Send USERS command */
5461       silc_server_packet_send(server, server->router->connection,
5462                               SILC_PACKET_COMMAND, cmd->packet->flags,
5463                               tmpbuf->data, tmpbuf->len, TRUE);
5464       
5465       /* Reprocess this packet after received reply */
5466       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5467                                   silc_command_get_ident(cmd->payload),
5468                                   silc_server_command_users,
5469                                   silc_server_command_dup(cmd));
5470       cmd->pending = TRUE;
5471       silc_command_set_ident(cmd->payload, ident);
5472       silc_buffer_free(tmpbuf);
5473       silc_free(id);
5474       goto out;
5475     }
5476
5477     /* Check the global list as well. */
5478     if (id)
5479       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5480     else
5481       channel = silc_idlist_find_channel_by_name(server->global_list, 
5482                                                  channel_name, NULL);
5483     if (!channel) {
5484       /* Channel really does not exist */
5485       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5486                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5487                                             0);
5488       goto out;
5489     }
5490   }
5491
5492   /* If the channel is private or secret do not send anything, unless the
5493      user requesting this command is on the channel or is server */
5494   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5495     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5496         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5497                                           NULL)) {
5498       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5499                                             SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5500       goto out;
5501     }
5502   }
5503
5504   /* Get the users list */
5505   silc_server_get_users_on_channel(server, channel, &client_id_list,
5506                                    &client_mode_list, &list_count);
5507
5508   /* List count */
5509   SILC_PUT32_MSB(list_count, lc);
5510
5511   /* Send reply */
5512   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5513   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5514                                                 SILC_STATUS_OK, 0, ident, 4,
5515                                                 2, idp->data, idp->len,
5516                                                 3, lc, 4,
5517                                                 4, client_id_list->data,
5518                                                 client_id_list->len,
5519                                                 5, client_mode_list->data,
5520                                                 client_mode_list->len);
5521   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5522                           packet->data, packet->len, FALSE);
5523     
5524   silc_buffer_free(idp);
5525   silc_buffer_free(packet);
5526   silc_buffer_free(client_id_list);
5527   silc_buffer_free(client_mode_list);
5528   silc_free(id);
5529
5530  out:
5531   silc_server_command_free(cmd);
5532 }
5533
5534 /* Server side of command GETKEY. This fetches the client's public key
5535    from the server where to the client is connected. */
5536
5537 SILC_SERVER_CMD_FUNC(getkey)
5538 {
5539   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5540   SilcServer server = cmd->server;
5541   SilcBuffer packet;
5542   SilcClientEntry client;
5543   SilcServerEntry server_entry;
5544   SilcClientID *client_id = NULL;
5545   SilcServerID *server_id = NULL;
5546   SilcIDPayload idp = NULL;
5547   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5548   unsigned char *tmp, *pkdata;
5549   SilcUInt32 tmp_len, pklen;
5550   SilcBuffer pk = NULL;
5551   SilcIdType id_type;
5552   SilcPublicKey public_key;
5553
5554   SILC_LOG_DEBUG(("Start"));
5555
5556   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5557   if (!tmp) {
5558     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5559                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5560                                           0);
5561     goto out;
5562   }
5563   idp = silc_id_payload_parse(tmp, tmp_len);
5564   if (!idp) {
5565     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5566                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5567                                           0);
5568     goto out;
5569   }
5570
5571   id_type = silc_id_payload_get_type(idp);
5572   if (id_type == SILC_ID_CLIENT) {
5573     client_id = silc_id_payload_get_id(idp);
5574
5575     /* If the client is not found from local list there is no chance it
5576        would be locally connected client so send the command further. */
5577     client = silc_idlist_find_client_by_id(server->local_list, 
5578                                            client_id, TRUE, NULL);
5579     if (!client)
5580       client = silc_idlist_find_client_by_id(server->global_list, 
5581                                              client_id, TRUE, NULL);
5582     
5583     if ((!client && !cmd->pending && !server->standalone) ||
5584         (client && !client->connection && !cmd->pending &&
5585          !(client->mode & SILC_UMODE_DETACHED)) ||
5586         (client && !client->data.public_key && !cmd->pending)) {
5587       SilcBuffer tmpbuf;
5588       SilcUInt16 old_ident;
5589       SilcSocketConnection dest_sock;
5590       
5591       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5592                                                client_id, NULL, NULL);
5593       if (!dest_sock)
5594         goto out;
5595       
5596       old_ident = silc_command_get_ident(cmd->payload);
5597       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5598       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5599       
5600       silc_server_packet_send(server, dest_sock,
5601                               SILC_PACKET_COMMAND, cmd->packet->flags,
5602                               tmpbuf->data, tmpbuf->len, TRUE);
5603       
5604       /* Reprocess this packet after received reply from router */
5605       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5606                                   silc_command_get_ident(cmd->payload),
5607                                   silc_server_command_getkey,
5608                                   silc_server_command_dup(cmd));
5609       cmd->pending = TRUE;
5610       silc_command_set_ident(cmd->payload, old_ident);
5611       silc_buffer_free(tmpbuf);
5612       goto out;
5613     }
5614
5615     if (!client) {
5616       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5617                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5618                                             0);
5619       goto out;
5620     }
5621
5622     /* The client is locally connected, just get the public key and
5623        send it back. If they key does not exist then do not send it, 
5624        send just OK reply */
5625     public_key = client->data.public_key;
5626     if (!public_key) {
5627       pkdata = NULL;
5628       pklen = 0;
5629     } else {
5630       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5631       pk = silc_buffer_alloc(4 + tmp_len);
5632       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5633       silc_buffer_format(pk,
5634                          SILC_STR_UI_SHORT(tmp_len),
5635                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5636                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5637                          SILC_STR_END);
5638       silc_free(tmp);
5639       pkdata = pk->data;
5640       pklen = pk->len;
5641     }
5642   } else if (id_type == SILC_ID_SERVER) {
5643     server_id = silc_id_payload_get_id(idp);
5644
5645     /* If the server is not found from local list there is no chance it
5646        would be locally connected server so send the command further. */
5647     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5648                                                  server_id, TRUE, NULL);
5649     if (!server_entry)
5650       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5651                                                    server_id, TRUE, NULL);
5652     
5653     if (server_entry != server->id_entry &&
5654         ((!server_entry && !cmd->pending && !server->standalone) ||
5655          (server_entry && !server_entry->connection && !cmd->pending &&
5656           !server->standalone) ||
5657          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5658           !server->standalone))) {
5659       SilcBuffer tmpbuf;
5660       SilcUInt16 old_ident;
5661       
5662       old_ident = silc_command_get_ident(cmd->payload);
5663       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5664       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5665       
5666       silc_server_packet_send(server, server->router->connection,
5667                               SILC_PACKET_COMMAND, cmd->packet->flags,
5668                               tmpbuf->data, tmpbuf->len, TRUE);
5669       
5670       /* Reprocess this packet after received reply from router */
5671       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5672                                   silc_command_get_ident(cmd->payload),
5673                                   silc_server_command_getkey,
5674                                   silc_server_command_dup(cmd));
5675       cmd->pending = TRUE;
5676       silc_command_set_ident(cmd->payload, old_ident);
5677       silc_buffer_free(tmpbuf);
5678       goto out;
5679     }
5680
5681     if (!server_entry) {
5682       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5683                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5684                                             0);
5685       goto out;
5686     }
5687
5688     /* If they key does not exist then do not send it, send just OK reply */
5689     public_key = (!server_entry->data.public_key ? 
5690                   (server_entry == server->id_entry ? server->public_key :
5691                    NULL) : server_entry->data.public_key);
5692     if (!public_key) {
5693       pkdata = NULL;
5694       pklen = 0;
5695     } else {
5696       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5697       pk = silc_buffer_alloc(4 + tmp_len);
5698       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5699       silc_buffer_format(pk,
5700                          SILC_STR_UI_SHORT(tmp_len),
5701                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5702                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5703                          SILC_STR_END);
5704       silc_free(tmp);
5705       pkdata = pk->data;
5706       pklen = pk->len;
5707     }
5708   } else {
5709     goto out;
5710   }
5711
5712   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5713   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5714                                                 SILC_STATUS_OK, 0, ident, 
5715                                                 pkdata ? 2 : 1,
5716                                                 2, tmp, tmp_len,
5717                                                 3, pkdata, pklen);
5718   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5719                           packet->data, packet->len, FALSE);
5720   silc_buffer_free(packet);
5721
5722   if (pk)
5723     silc_buffer_free(pk);
5724
5725  out:
5726   if (idp)
5727     silc_id_payload_free(idp);
5728   silc_free(client_id);
5729   silc_free(server_id);
5730   silc_server_command_free(cmd);
5731 }
5732
5733
5734 /* Private range commands, specific to this implementation */
5735
5736 /* Server side command of CONNECT. Connects us to the specified remote
5737    server or router. */
5738
5739 SILC_SERVER_CMD_FUNC(connect)
5740 {
5741   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5742   SilcServer server = cmd->server;
5743   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5744   unsigned char *tmp, *host;
5745   SilcUInt32 tmp_len;
5746   SilcUInt32 port = SILC_PORT;
5747
5748   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5749
5750   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5751     goto out;
5752
5753   /* Check whether client has the permissions. */
5754   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5755       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5756     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5757                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5758     goto out;
5759   }
5760
5761   if (server->server_type == SILC_ROUTER && 
5762       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5763     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5764                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5765     goto out;
5766   }
5767
5768   /* Get the remote server */
5769   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5770   if (!host) {
5771     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5772                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5773                                           0);
5774     goto out;
5775   }
5776
5777   /* Get port */
5778   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5779   if (tmp)
5780     SILC_GET32_MSB(port, tmp);
5781
5782   /* Create the connection. It is done with timeout and is async. */
5783   silc_server_create_connection(server, host, port);
5784
5785   /* Send reply to the sender */
5786   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5787                                         SILC_STATUS_OK, 0);
5788
5789  out:
5790   silc_server_command_free(cmd);
5791 }
5792
5793 /* Server side command of CLOSE. Closes connection to a specified server. */
5794  
5795 SILC_SERVER_CMD_FUNC(close)
5796 {
5797   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5798   SilcServer server = cmd->server;
5799   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5800   SilcServerEntry server_entry;
5801   SilcSocketConnection sock;
5802   unsigned char *tmp;
5803   SilcUInt32 tmp_len;
5804   unsigned char *name;
5805   SilcUInt32 port = SILC_PORT;
5806
5807   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5808
5809   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5810     goto out;
5811
5812   /* Check whether client has the permissions. */
5813   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5814       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5815     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5816                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5817                                           0);
5818     goto out;
5819   }
5820
5821   /* Get the remote server */
5822   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5823   if (!name) {
5824     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5825                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5826                                           0);
5827     goto out;
5828   }
5829
5830   /* Get port */
5831   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5832   if (tmp)
5833     SILC_GET32_MSB(port, tmp);
5834
5835   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5836                                                  name, port, FALSE, NULL);
5837   if (!server_entry)
5838     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5839                                                    name, port, FALSE, NULL);
5840   if (!server_entry) {
5841     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5842                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5843     goto out;
5844   }
5845
5846   /* Send reply to the sender */
5847   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5848                                         SILC_STATUS_OK, 0);
5849
5850   /* Close the connection to the server */
5851   sock = (SilcSocketConnection)server_entry->connection;
5852
5853   /* If we shutdown primary router connection manually then don't trigger
5854      any reconnect or backup router connections, by setting the router
5855      to NULL here. */
5856   if (server->router == server_entry) {
5857     server->id_entry->router = NULL;
5858     server->router = NULL;
5859     server->standalone = TRUE;
5860   }
5861   silc_server_free_sock_user_data(server, sock, NULL);
5862   silc_server_close_connection(server, sock);
5863   
5864  out:
5865   silc_server_command_free(cmd);
5866 }
5867
5868 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5869    active connections. */
5870  
5871 SILC_SERVER_CMD_FUNC(shutdown)
5872 {
5873   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5874   SilcServer server = cmd->server;
5875   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5876
5877   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5878
5879   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5880     goto out;
5881
5882   /* Check whether client has the permission. */
5883   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5884       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5885     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5886                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5887                                           0);
5888     goto out;
5889   }
5890
5891   /* Send reply to the sender */
5892   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5893                                         SILC_STATUS_OK, 0);
5894
5895   /* Then, gracefully, or not, bring the server down. */
5896   silc_server_stop(server);
5897   exit(0);
5898
5899  out:
5900   silc_server_command_free(cmd);
5901 }