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