updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       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 = silc_memdup(tmp, strlen(tmp));
3829     }
3830   } else {
3831     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832       /* Passphrase mode is unset. remove the passphrase */
3833       silc_free(channel->passphrase);
3834       channel->passphrase = NULL;
3835     }
3836   }
3837
3838   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3839     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3840       /* Cipher to use protect the traffic */
3841       SilcCipher newkey, oldkey;
3842
3843       /* Get cipher */
3844       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3845       if (!cipher) {
3846         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3847                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3848         goto out;
3849       }
3850
3851       /* Delete old cipher and allocate the new one */
3852       if (!silc_cipher_alloc(cipher, &newkey)) {
3853         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3855         goto out;
3856       }
3857
3858       oldkey = channel->channel_key;
3859       channel->channel_key = newkey;
3860
3861       /* Re-generate channel key */
3862       if (!silc_server_create_channel_key(server, channel, 0)) {
3863         /* We don't have new key, revert to old one */
3864         channel->channel_key = oldkey;
3865         goto out;
3866       }
3867
3868       /* Remove old channel key for good */
3869       silc_cipher_free(oldkey);
3870
3871       /* Send the channel key. This sends it to our local clients and if
3872          we are normal server to our router as well. */
3873       silc_server_send_channel_key(server, NULL, channel, 
3874                                    server->server_type == SILC_ROUTER ? 
3875                                    FALSE : !server->standalone);
3876     }
3877   } else {
3878     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3879       /* Cipher mode is unset. Remove the cipher and revert back to 
3880          default cipher */
3881       SilcCipher newkey, oldkey;
3882       cipher = channel->cipher;
3883
3884       /* Delete old cipher and allocate default one */
3885       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3886         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3887                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3888         goto out;
3889       }
3890
3891       oldkey = channel->channel_key;
3892       channel->channel_key = newkey;
3893
3894       /* Re-generate channel key */
3895       if (!silc_server_create_channel_key(server, channel, 0)) {
3896         /* We don't have new key, revert to old one */
3897         channel->channel_key = oldkey;
3898         goto out;
3899       }
3900       
3901       /* Remove old channel key for good */
3902       silc_cipher_free(oldkey);
3903
3904       /* Send the channel key. This sends it to our local clients and if
3905          we are normal server to our router as well. */
3906       silc_server_send_channel_key(server, NULL, channel, 
3907                                    server->server_type == SILC_ROUTER ? 
3908                                    FALSE : !server->standalone);
3909     }
3910   }
3911
3912   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3913     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3914       /* HMAC to use protect the traffic */
3915       unsigned char hash[32];
3916       SilcHmac newhmac;
3917
3918       /* Get hmac */
3919       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3920       if (!hmac) {
3921         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3922                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3923         goto out;
3924       }
3925
3926       /* Delete old hmac and allocate the new one */
3927       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3928         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3929                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3930         goto out;
3931       }
3932
3933       silc_hmac_free(channel->hmac);
3934       channel->hmac = newhmac;
3935
3936       /* Set the HMAC key out of current channel key. The client must do
3937          this locally. */
3938       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3939                      channel->key_len / 8, hash);
3940       silc_hmac_set_key(channel->hmac, hash, 
3941                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3942       memset(hash, 0, sizeof(hash));
3943     }
3944   } else {
3945     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3946       /* Hmac mode is unset. Remove the hmac and revert back to 
3947          default hmac */
3948       SilcHmac newhmac;
3949       unsigned char hash[32];
3950       hmac = channel->hmac_name;
3951
3952       /* Delete old hmac and allocate default one */
3953       silc_hmac_free(channel->hmac);
3954       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3955         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3956                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3957         goto out;
3958       }
3959
3960       silc_hmac_free(channel->hmac);
3961       channel->hmac = newhmac;
3962
3963       /* Set the HMAC key out of current channel key. The client must do
3964          this locally. */
3965       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3966                      channel->key_len / 8, 
3967                      hash);
3968       silc_hmac_set_key(channel->hmac, hash, 
3969                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3970       memset(hash, 0, sizeof(hash));
3971     }
3972   }
3973
3974   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3975     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3976       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3977         /* Set the founder authentication */
3978         SilcAuthPayload auth;
3979         
3980         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3981         if (!tmp) {
3982           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3983                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3984           goto out;
3985         }
3986
3987         auth = silc_auth_payload_parse(tmp, tmp_len);
3988         if (!auth) {
3989           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3990                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3991           goto out;
3992         }
3993
3994         /* Save the public key */
3995         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3996         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3997         silc_free(tmp);
3998         
3999         channel->founder_method = silc_auth_get_method(auth);
4000
4001         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4002           tmp = silc_auth_get_data(auth, &tmp_len);
4003           channel->founder_passwd = silc_memdup(tmp, tmp_len);
4004           channel->founder_passwd_len = tmp_len;
4005         } else {
4006           /* Verify the payload before setting the mode */
4007           if (!silc_auth_verify(auth, channel->founder_method, 
4008                                 channel->founder_key, 0, idata->hash,
4009                                 client->id, SILC_ID_CLIENT)) {
4010             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4011                                                   SILC_STATUS_ERR_AUTH_FAILED);
4012             goto out;
4013           }
4014         }
4015
4016         silc_auth_payload_free(auth);
4017       }
4018     }
4019   } else {
4020     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4021       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4022         if (channel->founder_key)
4023           silc_pkcs_public_key_free(channel->founder_key);
4024         if (channel->founder_passwd) {
4025           silc_free(channel->founder_passwd);
4026           channel->founder_passwd = NULL;
4027         }
4028       }
4029     }
4030   }
4031
4032   /* Finally, set the mode */
4033   channel->mode = mode_mask;
4034
4035   /* Send CMODE_CHANGE notify. */
4036   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4037   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4038                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4039                                      cidp->data, cidp->len, 
4040                                      tmp_mask, 4,
4041                                      cipher, cipher ? strlen(cipher) : 0,
4042                                      hmac, hmac ? strlen(hmac) : 0,
4043                                      passphrase, passphrase ? 
4044                                      strlen(passphrase) : 0);
4045
4046   /* Set CMODE notify type to network */
4047   if (!server->standalone)
4048     silc_server_send_notify_cmode(server, server->router->connection,
4049                                   server->server_type == SILC_ROUTER ? 
4050                                   TRUE : FALSE, channel,
4051                                   mode_mask, client->id, SILC_ID_CLIENT,
4052                                   cipher, hmac, passphrase);
4053
4054   /* Send command reply to sender */
4055   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4056                                                 SILC_STATUS_OK, ident, 2,
4057                                                 2, tmp_id, tmp_len2,
4058                                                 3, tmp_mask, 4);
4059   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4060                           packet->data, packet->len, FALSE);
4061     
4062   silc_buffer_free(packet);
4063   silc_free(channel_id);
4064   silc_buffer_free(cidp);
4065
4066  out:
4067   silc_server_command_free(cmd);
4068 }
4069
4070 /* Server side of CUMODE command. Changes client's mode on a channel. */
4071
4072 SILC_SERVER_CMD_FUNC(cumode)
4073 {
4074   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4075   SilcServer server = cmd->server;
4076   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4077   SilcIDListData idata = (SilcIDListData)client;
4078   SilcChannelID *channel_id;
4079   SilcClientID *client_id;
4080   SilcChannelEntry channel;
4081   SilcClientEntry target_client;
4082   SilcChannelClientEntry chl;
4083   SilcBuffer packet, idp;
4084   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4085   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4086   int notify = FALSE;
4087   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4088
4089   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4090
4091   /* Get Channel ID */
4092   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4093   if (!tmp_ch_id) {
4094     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4095                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4096     goto out;
4097   }
4098   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4099   if (!channel_id) {
4100     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4101                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4102     goto out;
4103   }
4104
4105   /* Get channel entry */
4106   channel = silc_idlist_find_channel_by_id(server->local_list, 
4107                                            channel_id, NULL);
4108   if (!channel) {
4109     channel = silc_idlist_find_channel_by_id(server->global_list, 
4110                                              channel_id, NULL);
4111     if (!channel) {
4112       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4113                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4114       goto out;
4115     }
4116   }
4117
4118   /* Check whether sender is on the channel */
4119   if (!silc_server_client_on_channel(client, channel, &chl)) {
4120     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4121                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4122     goto out;
4123   }
4124   sender_mask = chl->mode;
4125   
4126   /* Get the target client's channel mode mask */
4127   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4128   if (!tmp_mask) {
4129     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4130                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4131     goto out;
4132   }
4133   SILC_GET32_MSB(target_mask, tmp_mask);
4134
4135   /* Get target Client ID */
4136   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4137   if (!tmp_id) {
4138     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4139                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4140     goto out;
4141   }
4142   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4143   if (!client_id) {
4144     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4145                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4146     goto out;
4147   }
4148
4149   /* Get target client's entry */
4150   target_client = silc_idlist_find_client_by_id(server->local_list, 
4151                                                 client_id, TRUE, NULL);
4152   if (!target_client) {
4153     target_client = silc_idlist_find_client_by_id(server->global_list, 
4154                                                   client_id, TRUE, NULL);
4155   }
4156
4157   if (target_client != client &&
4158       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4159       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4160     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4161                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4162     goto out;
4163   }
4164
4165   /* Check whether target client is on the channel */
4166   if (target_client != client) {
4167     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4168       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4169                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4170       goto out;
4171     }
4172   }
4173
4174   /* 
4175    * Change the mode 
4176    */
4177
4178   /* If the target client is founder, no one else can change their mode
4179      but themselves. */
4180   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4181     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4182                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4183     goto out;
4184   }
4185
4186   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4187     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4188       /* The client tries to claim the founder rights. */
4189       unsigned char *tmp_auth;
4190       SilcUInt32 tmp_auth_len, auth_len;
4191       void *auth;
4192       
4193       if (target_client != client) {
4194         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4195                                               SILC_STATUS_ERR_NOT_YOU);
4196         goto out;
4197       }
4198
4199       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4200           !channel->founder_key || !idata->public_key ||
4201           !silc_pkcs_public_key_compare(channel->founder_key, 
4202                                         idata->public_key)) {
4203         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4204                                               SILC_STATUS_ERR_NOT_YOU);
4205         goto out;
4206       }
4207
4208       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4209       if (!tmp_auth) {
4210         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4212         goto out;
4213       }
4214
4215       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4216               (void *)channel->founder_passwd : (void *)channel->founder_key);
4217       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4218                   channel->founder_passwd_len : 0);
4219       
4220       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4221                                  channel->founder_method, auth, auth_len,
4222                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4223         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224                                               SILC_STATUS_ERR_AUTH_FAILED);
4225         goto out;
4226       }
4227       
4228       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4229       notify = TRUE;
4230     }
4231   } else {
4232     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4233       if (target_client == client) {
4234         /* Remove channel founder rights from itself */
4235         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4236         notify = TRUE;
4237       } else {
4238         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239                                               SILC_STATUS_ERR_NOT_YOU);
4240         goto out;
4241       }
4242     }
4243   }
4244
4245   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4246     /* Promote to operator */
4247     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4248       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4249           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4250         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4251                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4252         goto out;
4253       }
4254
4255       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4256       notify = TRUE;
4257     }
4258   } else {
4259     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4260       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4261           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4262         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4263                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4264         goto out;
4265       }
4266
4267       /* Demote to normal user */
4268       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4269       notify = TRUE;
4270     }
4271   }
4272
4273   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4274   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4275
4276   /* Send notify to channel, notify only if mode was actually changed. */
4277   if (notify) {
4278     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4279                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4280                                        idp->data, idp->len,
4281                                        tmp_mask, 4, 
4282                                        tmp_id, tmp_len);
4283
4284     /* Set CUMODE notify type to network */
4285     if (!server->standalone)
4286       silc_server_send_notify_cumode(server, server->router->connection,
4287                                      server->server_type == SILC_ROUTER ? 
4288                                      TRUE : FALSE, channel,
4289                                      target_mask, client->id, 
4290                                      SILC_ID_CLIENT,
4291                                      target_client->id);
4292   }
4293
4294   /* Send command reply to sender */
4295   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4296                                                 SILC_STATUS_OK, ident, 3,
4297                                                 2, tmp_mask, 4,
4298                                                 3, tmp_ch_id, tmp_ch_len,
4299                                                 4, tmp_id, tmp_len);
4300   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4301                           packet->data, packet->len, FALSE);
4302     
4303   silc_buffer_free(packet);
4304   silc_free(channel_id);
4305   silc_free(client_id);
4306   silc_buffer_free(idp);
4307
4308  out:
4309   silc_server_command_free(cmd);
4310 }
4311
4312 /* Server side of KICK command. Kicks client out of channel. */
4313
4314 SILC_SERVER_CMD_FUNC(kick)
4315 {
4316   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4317   SilcServer server = cmd->server;
4318   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4319   SilcClientEntry target_client;
4320   SilcChannelID *channel_id;
4321   SilcClientID *client_id;
4322   SilcChannelEntry channel;
4323   SilcChannelClientEntry chl;
4324   SilcBuffer idp;
4325   SilcUInt32 tmp_len, target_idp_len;
4326   unsigned char *tmp, *comment, *target_idp;
4327
4328   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4329
4330   /* Get Channel ID */
4331   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4332   if (!tmp) {
4333     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4334                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4335     goto out;
4336   }
4337   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4338   if (!channel_id) {
4339     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4340                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4341     goto out;
4342   }
4343
4344   /* Get channel entry */
4345   channel = silc_idlist_find_channel_by_id(server->local_list, 
4346                                            channel_id, NULL);
4347   if (!channel) {
4348     channel = silc_idlist_find_channel_by_id(server->local_list, 
4349                                              channel_id, NULL);
4350     if (!channel) {
4351       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4352                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4353       goto out;
4354     }
4355   }
4356
4357   /* Check whether sender is on the channel */
4358   if (!silc_server_client_on_channel(client, channel, &chl)) {
4359     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4360                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4361     goto out;
4362   }
4363
4364   /* Check that the kicker is channel operator or channel founder */
4365   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4366     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4367                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4368     goto out;
4369   }
4370   
4371   /* Get target Client ID */
4372   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4373   if (!target_idp) {
4374     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4375                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4376     goto out;
4377   }
4378   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4379   if (!client_id) {
4380     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4381                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4382     goto out;
4383   }
4384
4385   /* Get target client's entry */
4386   target_client = silc_idlist_find_client_by_id(server->local_list, 
4387                                                 client_id, TRUE, NULL);
4388   if (!target_client) {
4389     target_client = silc_idlist_find_client_by_id(server->global_list, 
4390                                                   client_id, TRUE, NULL);
4391   }
4392
4393   /* Check whether target client is on the channel */
4394   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4395     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4396                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4397     goto out;
4398   }
4399
4400   /* Check that the target client is not channel founder. Channel founder
4401      cannot be kicked from the channel. */
4402   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4403     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4404                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4405     goto out;
4406   }
4407   
4408   /* Get comment */
4409   tmp_len = 0;
4410   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4411   if (tmp_len > 128)
4412     comment = NULL;
4413
4414   /* Send command reply to sender */
4415   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4416                                         SILC_STATUS_OK);
4417
4418   /* Send KICKED notify to local clients on the channel */
4419   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4420   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4421                                      SILC_NOTIFY_TYPE_KICKED, 3,
4422                                      target_idp, target_idp_len,
4423                                      comment, comment ? strlen(comment) : 0,
4424                                      idp->data, idp->len);
4425   silc_buffer_free(idp);
4426
4427   /* Remove the client from the channel. If the channel does not exist
4428      after removing the client then the client kicked itself off the channel
4429      and we don't have to send anything after that. */
4430   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4431                                            target_client, FALSE))
4432     goto out;
4433
4434   /* Send KICKED notify to primary route */
4435   if (!server->standalone)
4436     silc_server_send_notify_kicked(server, server->router->connection,
4437                                    server->server_type == SILC_ROUTER ?
4438                                    TRUE : FALSE, channel,
4439                                    target_client->id, client->id, comment);
4440
4441   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4442     /* Re-generate channel key */
4443     if (!silc_server_create_channel_key(server, channel, 0))
4444       goto out;
4445     
4446     /* Send the channel key to the channel. The key of course is not sent
4447        to the client who was kicked off the channel. */
4448     silc_server_send_channel_key(server, target_client->connection, channel, 
4449                                  server->server_type == SILC_ROUTER ? 
4450                                  FALSE : !server->standalone);
4451   }
4452
4453  out:
4454   silc_server_command_free(cmd);
4455 }
4456
4457 /* Server side of OPER command. Client uses this comand to obtain server
4458    operator privileges to this server/router. */
4459
4460 SILC_SERVER_CMD_FUNC(oper)
4461 {
4462   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4463   SilcServer server = cmd->server;
4464   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4465   unsigned char *username, *auth;
4466   SilcUInt32 tmp_len;
4467   SilcServerConfigAdmin *admin;
4468   SilcIDListData idata = (SilcIDListData)client;
4469   bool result = FALSE;
4470   SilcPublicKey cached_key;
4471
4472   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4473
4474   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4475     goto out;
4476
4477   /* Get the username */
4478   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4479   if (!username) {
4480     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4481                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4482     goto out;
4483   }
4484
4485   /* Get the admin configuration */
4486   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4487                                         username, client->nickname);
4488   if (!admin) {
4489     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4490                                           username, client->nickname);
4491     if (!admin) {
4492       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4493                                             SILC_STATUS_ERR_AUTH_FAILED);
4494       goto out;
4495     }
4496   }
4497
4498   /* Get the authentication payload */
4499   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4500   if (!auth) {
4501     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4502                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4503     goto out;
4504   }
4505
4506   /* Verify the authentication data. If both passphrase and public key
4507      is set then try both of them. */
4508   if (admin->passphrase)
4509     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4510                                    admin->passphrase, admin->passphrase_len,
4511                                    idata->hash, client->id, SILC_ID_CLIENT);
4512   if (!result && admin->publickeys) {
4513     cached_key = silc_server_get_public_key(server, admin->publickeys);
4514     if (!cached_key)
4515       goto out;
4516     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4517                                    cached_key, 0, idata->hash, 
4518                                    client->id, SILC_ID_CLIENT);
4519   }
4520   if (!result) {
4521     /* Authentication failed */
4522     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4523                                           SILC_STATUS_ERR_AUTH_FAILED);
4524     goto out;
4525   }
4526
4527   /* Client is now server operator */
4528   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4529
4530   /* Update statistics */
4531   if (client->connection)
4532     server->stat.my_server_ops++;
4533   if (server->server_type == SILC_ROUTER)
4534     server->stat.server_ops++;
4535
4536   /* Send UMODE change to primary router */
4537   if (!server->standalone)
4538     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4539                                   client->id, client->mode);
4540
4541   /* Send reply to the sender */
4542   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4543                                         SILC_STATUS_OK);
4544
4545  out:
4546   silc_server_command_free(cmd);
4547 }
4548
4549 /* Server side of SILCOPER command. Client uses this comand to obtain router
4550    operator privileges to this router. */
4551
4552 SILC_SERVER_CMD_FUNC(silcoper)
4553 {
4554   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4555   SilcServer server = cmd->server;
4556   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4557   unsigned char *username, *auth;
4558   SilcUInt32 tmp_len;
4559   SilcServerConfigAdmin *admin;
4560   SilcIDListData idata = (SilcIDListData)client;
4561   bool result = FALSE;
4562   SilcPublicKey cached_key;
4563
4564   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4565
4566   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4567     goto out;
4568
4569   if (server->server_type != SILC_ROUTER) {
4570     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4571                                           SILC_STATUS_ERR_AUTH_FAILED);
4572     goto out;
4573   }
4574
4575   /* Get the username */
4576   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4577   if (!username) {
4578     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4579                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4580     goto out;
4581   }
4582
4583   /* Get the admin configuration */
4584   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4585                                         username, client->nickname);
4586   if (!admin) {
4587     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4588                                           username, client->nickname);
4589     if (!admin) {
4590       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4591                                             SILC_STATUS_ERR_AUTH_FAILED);
4592       goto out;
4593     }
4594   }
4595
4596   /* Get the authentication payload */
4597   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4598   if (!auth) {
4599     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4600                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4601     goto out;
4602   }
4603
4604   /* Verify the authentication data. If both passphrase and public key
4605      is set then try both of them. */
4606   if (admin->passphrase)
4607     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4608                                    admin->passphrase, admin->passphrase_len,
4609                                    idata->hash, client->id, SILC_ID_CLIENT);
4610   if (!result && admin->publickeys) {
4611     cached_key = silc_server_get_public_key(server, admin->publickeys);
4612     if (!cached_key)
4613       goto out;
4614     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4615                                    cached_key, 0, idata->hash, 
4616                                    client->id, SILC_ID_CLIENT);
4617   }
4618   if (!result) {
4619     /* Authentication failed */
4620     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4621                                           SILC_STATUS_ERR_AUTH_FAILED);
4622     goto out;
4623   }
4624
4625   /* Client is now router operator */
4626   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4627
4628   /* Update statistics */
4629   if (client->connection)
4630     server->stat.my_router_ops++;
4631   if (server->server_type == SILC_ROUTER)
4632     server->stat.router_ops++;
4633
4634   /* Send UMODE change to primary router */
4635   if (!server->standalone)
4636     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4637                                   client->id, client->mode);
4638
4639   /* Send reply to the sender */
4640   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4641                                         SILC_STATUS_OK);
4642
4643  out:
4644   silc_server_command_free(cmd);
4645 }
4646
4647 /* Server side of command BAN. This is used to manage the ban list of the
4648    channel. To add clients and remove clients from the ban list. */
4649
4650 SILC_SERVER_CMD_FUNC(ban)
4651 {
4652   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4653   SilcServer server = cmd->server;
4654   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4655   SilcBuffer packet;
4656   SilcChannelEntry channel;
4657   SilcChannelClientEntry chl;
4658   SilcChannelID *channel_id = NULL;
4659   unsigned char *id, *add, *del;
4660   SilcUInt32 id_len, tmp_len;
4661   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4662
4663   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4664     goto out;
4665
4666   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4667
4668   /* Get Channel ID */
4669   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4670   if (id) {
4671     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4672     if (!channel_id) {
4673       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4674                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4675       goto out;
4676     }
4677   }
4678
4679   /* Get channel entry. The server must know about the channel since the
4680      client is expected to be on the channel. */
4681   channel = silc_idlist_find_channel_by_id(server->local_list, 
4682                                            channel_id, NULL);
4683   if (!channel) {
4684     channel = silc_idlist_find_channel_by_id(server->global_list, 
4685                                              channel_id, NULL);
4686     if (!channel) {
4687       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4688                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4689       goto out;
4690     }
4691   }
4692
4693   /* Check whether this client is on the channel */
4694   if (!silc_server_client_on_channel(client, channel, &chl)) {
4695     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4696                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4697     goto out;
4698   }
4699
4700   /* The client must be at least channel operator. */
4701   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4702     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4703                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4704     goto out;
4705   }
4706
4707   /* Get the new ban and add it to the ban list */
4708   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4709   if (add) {
4710     if (!channel->ban_list)
4711       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4712     else
4713       channel->ban_list = silc_realloc(channel->ban_list, 
4714                                        sizeof(*channel->ban_list) * 
4715                                        (tmp_len + 
4716                                         strlen(channel->ban_list) + 2));
4717     if (add[tmp_len - 1] == ',')
4718       add[tmp_len - 1] = '\0';
4719
4720     strncat(channel->ban_list, add, tmp_len);
4721     strncat(channel->ban_list, ",", 1);
4722   }
4723
4724   /* Get the ban to be removed and remove it from the list */
4725   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4726   if (del && channel->ban_list) {
4727     char *start, *end, *n;
4728
4729     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4730       silc_free(channel->ban_list);
4731       channel->ban_list = NULL;
4732     } else {
4733       start = strstr(channel->ban_list, del);
4734       if (start && strlen(start) >= tmp_len) {
4735         end = start + tmp_len;
4736         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4737         strncat(n, channel->ban_list, start - channel->ban_list);
4738         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4739                              end) - 1);
4740         silc_free(channel->ban_list);
4741         channel->ban_list = n;
4742       }
4743     }
4744   }
4745
4746   /* Send the BAN notify type to our primary router. */
4747   if (!server->standalone && (add || del))
4748     silc_server_send_notify_ban(server, server->router->connection,
4749                                 server->server_type == SILC_ROUTER ?
4750                                 TRUE : FALSE, channel, add, del);
4751
4752   /* Send the reply back to the client */
4753   packet = 
4754     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4755                                          SILC_STATUS_OK, ident, 2,
4756                                          2, id, id_len,
4757                                          3, channel->ban_list, 
4758                                          channel->ban_list ? 
4759                                          strlen(channel->ban_list) -1 : 0);
4760   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4761                           packet->data, packet->len, FALSE);
4762     
4763   silc_buffer_free(packet);
4764
4765  out:
4766   silc_free(channel_id);
4767   silc_server_command_free(cmd);
4768 }
4769
4770 /* Server side command of LEAVE. Removes client from a channel. */
4771
4772 SILC_SERVER_CMD_FUNC(leave)
4773 {
4774   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4775   SilcServer server = cmd->server;
4776   SilcSocketConnection sock = cmd->sock;
4777   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4778   SilcChannelID *id = NULL;
4779   SilcChannelEntry channel;
4780   SilcUInt32 len;
4781   unsigned char *tmp;
4782
4783   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4784
4785   /* Get Channel ID */
4786   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4787   if (!tmp) {
4788     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4789                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4790     goto out;
4791   }
4792   id = silc_id_payload_parse_id(tmp, len, NULL);
4793   if (!id) {
4794     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4795                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4796     goto out;
4797   }
4798
4799   /* Get channel entry */
4800   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4801   if (!channel) {
4802     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4803     if (!channel) {
4804       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4805                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4806       goto out;
4807     }
4808   }
4809
4810   /* Check whether this client is on the channel */
4811   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4812     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4813                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4814     goto out;
4815   }
4816
4817   /* Notify routers that they should remove this client from their list
4818      of clients on the channel. Send LEAVE notify type. */
4819   if (!server->standalone)
4820     silc_server_send_notify_leave(server, server->router->connection,
4821                                   server->server_type == SILC_ROUTER ?
4822                                   TRUE : FALSE, channel, id_entry->id);
4823
4824   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4825                                        SILC_STATUS_OK, 2, tmp, len);
4826
4827   /* Remove client from channel */
4828   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4829                                            TRUE))
4830     /* If the channel does not exist anymore we won't send anything */
4831     goto out;
4832
4833   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4834     /* Re-generate channel key */
4835     if (!silc_server_create_channel_key(server, channel, 0))
4836       goto out;
4837
4838     /* Send the channel key */
4839     silc_server_send_channel_key(server, NULL, channel, 
4840                                  server->server_type == SILC_ROUTER ? 
4841                                  FALSE : !server->standalone);
4842   }
4843
4844  out:
4845   silc_free(id);
4846   silc_server_command_free(cmd);
4847 }
4848
4849 /* Server side of command USERS. Resolves clients and their USERS currently
4850    joined on the requested channel. The list of Client ID's and their modes
4851    on the channel is sent back. */
4852
4853 SILC_SERVER_CMD_FUNC(users)
4854 {
4855   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4856   SilcServer server = cmd->server;
4857   SilcChannelEntry channel;
4858   SilcChannelID *id = NULL;
4859   SilcBuffer packet, idp;
4860   unsigned char *channel_id;
4861   SilcUInt32 channel_id_len;
4862   SilcBuffer client_id_list;
4863   SilcBuffer client_mode_list;
4864   unsigned char lc[4];
4865   SilcUInt32 list_count = 0;
4866   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4867   char *channel_name;
4868
4869   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4870
4871   /* Get Channel ID */
4872   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4873
4874   /* Get channel name */
4875   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4876
4877   if (!channel_id && !channel_name) {
4878     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4879                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4880     goto out;
4881   }
4882
4883   if (channel_id) {
4884     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4885     if (!id) {
4886       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4887                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4888       goto out;
4889     }
4890   }
4891
4892   /* If we are server and we don't know about this channel we will send
4893      the command to our router. If we know about the channel then we also
4894      have the list of users already. */
4895   if (id)
4896     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4897   else
4898     channel = silc_idlist_find_channel_by_name(server->local_list, 
4899                                                channel_name, NULL);
4900
4901   if (!channel || channel->disabled) {
4902     if (server->server_type != SILC_ROUTER && !server->standalone &&
4903         !cmd->pending) {
4904       SilcBuffer tmpbuf;
4905       
4906       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4907       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4908       
4909       /* Send USERS command */
4910       silc_server_packet_send(server, server->router->connection,
4911                               SILC_PACKET_COMMAND, cmd->packet->flags,
4912                               tmpbuf->data, tmpbuf->len, TRUE);
4913       
4914       /* Reprocess this packet after received reply */
4915       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4916                                   silc_command_get_ident(cmd->payload),
4917                                   silc_server_command_users,
4918                                   silc_server_command_dup(cmd));
4919       cmd->pending = TRUE;
4920       silc_command_set_ident(cmd->payload, ident);
4921       silc_buffer_free(tmpbuf);
4922       silc_free(id);
4923       goto out;
4924     }
4925
4926     /* Check the global list as well. */
4927     if (id)
4928       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4929     else
4930       channel = silc_idlist_find_channel_by_name(server->global_list, 
4931                                                  channel_name, NULL);
4932     if (!channel) {
4933       /* Channel really does not exist */
4934       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4935                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4936       goto out;
4937     }
4938   }
4939
4940   /* If the channel is private or secret do not send anything, unless the
4941      user requesting this command is on the channel. */
4942   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4943     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4944         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
4945                                           NULL)) {
4946       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4947                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4948       goto out;
4949     }
4950   } else {
4951     if (channel->mode & 
4952         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
4953       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4954                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4955       goto out;
4956     }
4957   }
4958
4959   /* Get the users list */
4960   silc_server_get_users_on_channel(server, channel, &client_id_list,
4961                                    &client_mode_list, &list_count);
4962
4963   /* List count */
4964   SILC_PUT32_MSB(list_count, lc);
4965
4966   /* Send reply */
4967   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4968   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4969                                                 SILC_STATUS_OK, ident, 4,
4970                                                 2, idp->data, idp->len,
4971                                                 3, lc, 4,
4972                                                 4, client_id_list->data,
4973                                                 client_id_list->len,
4974                                                 5, client_mode_list->data,
4975                                                 client_mode_list->len);
4976   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4977                           packet->data, packet->len, FALSE);
4978     
4979   silc_buffer_free(idp);
4980   silc_buffer_free(packet);
4981   silc_buffer_free(client_id_list);
4982   silc_buffer_free(client_mode_list);
4983   silc_free(id);
4984
4985  out:
4986   silc_server_command_free(cmd);
4987 }
4988
4989 /* Server side of command GETKEY. This fetches the client's public key
4990    from the server where to the client is connected. */
4991
4992 SILC_SERVER_CMD_FUNC(getkey)
4993 {
4994   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4995   SilcServer server = cmd->server;
4996   SilcBuffer packet;
4997   SilcClientEntry client;
4998   SilcServerEntry server_entry;
4999   SilcClientID *client_id = NULL;
5000   SilcServerID *server_id = NULL;
5001   SilcIDPayload idp = NULL;
5002   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5003   unsigned char *tmp, *pkdata;
5004   SilcUInt32 tmp_len, pklen;
5005   SilcBuffer pk = NULL;
5006   SilcIdType id_type;
5007   SilcPublicKey public_key;
5008
5009   SILC_LOG_DEBUG(("Start"));
5010
5011   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5012   if (!tmp) {
5013     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5014                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5015     goto out;
5016   }
5017   idp = silc_id_payload_parse(tmp, tmp_len);
5018   if (!idp) {
5019     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5020                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5021     goto out;
5022   }
5023
5024   id_type = silc_id_payload_get_type(idp);
5025   if (id_type == SILC_ID_CLIENT) {
5026     client_id = silc_id_payload_get_id(idp);
5027
5028     /* If the client is not found from local list there is no chance it
5029        would be locally connected client so send the command further. */
5030     client = silc_idlist_find_client_by_id(server->local_list, 
5031                                            client_id, TRUE, NULL);
5032     if (!client)
5033       client = silc_idlist_find_client_by_id(server->global_list, 
5034                                              client_id, TRUE, NULL);
5035     
5036     if ((!client && !cmd->pending && !server->standalone) ||
5037         (client && !client->connection && !cmd->pending) ||
5038         (client && !client->data.public_key && !cmd->pending)) {
5039       SilcBuffer tmpbuf;
5040       SilcUInt16 old_ident;
5041       SilcSocketConnection dest_sock;
5042       
5043       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5044                                                client_id, NULL);
5045       if (!dest_sock)
5046         goto out;
5047       
5048       old_ident = silc_command_get_ident(cmd->payload);
5049       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5050       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5051       
5052       silc_server_packet_send(server, dest_sock,
5053                               SILC_PACKET_COMMAND, cmd->packet->flags,
5054                               tmpbuf->data, tmpbuf->len, TRUE);
5055       
5056       /* Reprocess this packet after received reply from router */
5057       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5058                                   silc_command_get_ident(cmd->payload),
5059                                   silc_server_command_getkey,
5060                                   silc_server_command_dup(cmd));
5061       cmd->pending = TRUE;
5062       silc_command_set_ident(cmd->payload, old_ident);
5063       silc_buffer_free(tmpbuf);
5064       goto out;
5065     }
5066
5067     if (!client) {
5068       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5069                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5070       goto out;
5071     }
5072
5073     /* The client is locally connected, just get the public key and
5074        send it back. If they key does not exist then do not send it, 
5075        send just OK reply */
5076     public_key = client->data.public_key;
5077     if (!public_key) {
5078       pkdata = NULL;
5079       pklen = 0;
5080     } else {
5081       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5082       pk = silc_buffer_alloc(4 + tmp_len);
5083       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5084       silc_buffer_format(pk,
5085                          SILC_STR_UI_SHORT(tmp_len),
5086                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5087                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5088                          SILC_STR_END);
5089       silc_free(tmp);
5090       pkdata = pk->data;
5091       pklen = pk->len;
5092     }
5093   } else if (id_type == SILC_ID_SERVER) {
5094     server_id = silc_id_payload_get_id(idp);
5095
5096     /* If the server is not found from local list there is no chance it
5097        would be locally connected server so send the command further. */
5098     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5099                                                  server_id, TRUE, NULL);
5100     if (!server_entry)
5101       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5102                                                    server_id, TRUE, NULL);
5103     
5104     if (server_entry != server->id_entry &&
5105         ((!server_entry && !cmd->pending && !server->standalone) ||
5106          (server_entry && !server_entry->connection && !cmd->pending &&
5107           !server->standalone) ||
5108          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5109           !server->standalone))) {
5110       SilcBuffer tmpbuf;
5111       SilcUInt16 old_ident;
5112       
5113       old_ident = silc_command_get_ident(cmd->payload);
5114       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5115       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5116       
5117       silc_server_packet_send(server, server->router->connection,
5118                               SILC_PACKET_COMMAND, cmd->packet->flags,
5119                               tmpbuf->data, tmpbuf->len, TRUE);
5120       
5121       /* Reprocess this packet after received reply from router */
5122       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5123                                   silc_command_get_ident(cmd->payload),
5124                                   silc_server_command_getkey,
5125                                   silc_server_command_dup(cmd));
5126       cmd->pending = TRUE;
5127       silc_command_set_ident(cmd->payload, old_ident);
5128       silc_buffer_free(tmpbuf);
5129       goto out;
5130     }
5131
5132     if (!server_entry) {
5133       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5134                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5135       goto out;
5136     }
5137
5138     /* If they key does not exist then do not send it, send just OK reply */
5139     public_key = (!server_entry->data.public_key ? 
5140                   (server_entry == server->id_entry ? server->public_key :
5141                    NULL) : server_entry->data.public_key);
5142     if (!public_key) {
5143       pkdata = NULL;
5144       pklen = 0;
5145     } else {
5146       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5147       pk = silc_buffer_alloc(4 + tmp_len);
5148       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5149       silc_buffer_format(pk,
5150                          SILC_STR_UI_SHORT(tmp_len),
5151                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5152                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5153                          SILC_STR_END);
5154       silc_free(tmp);
5155       pkdata = pk->data;
5156       pklen = pk->len;
5157     }
5158   } else {
5159     goto out;
5160   }
5161
5162   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5163   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5164                                                 SILC_STATUS_OK, ident, 
5165                                                 pkdata ? 2 : 1,
5166                                                 2, tmp, tmp_len,
5167                                                 3, pkdata, pklen);
5168   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5169                           packet->data, packet->len, FALSE);
5170   silc_buffer_free(packet);
5171
5172   if (pk)
5173     silc_buffer_free(pk);
5174
5175  out:
5176   if (idp)
5177     silc_id_payload_free(idp);
5178   silc_free(client_id);
5179   silc_free(server_id);
5180   silc_server_command_free(cmd);
5181 }
5182
5183
5184 /* Private range commands, specific to this implementation */
5185
5186 /* Server side command of CONNECT. Connects us to the specified remote
5187    server or router. */
5188
5189 SILC_SERVER_CMD_FUNC(connect)
5190 {
5191   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5192   SilcServer server = cmd->server;
5193   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5194   unsigned char *tmp, *host;
5195   SilcUInt32 tmp_len;
5196   SilcUInt32 port = SILC_PORT;
5197
5198   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5199
5200   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5201     goto out;
5202
5203   /* Check whether client has the permissions. */
5204   if (client->mode == SILC_UMODE_NONE) {
5205     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5206                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5207     goto out;
5208   }
5209
5210   if (server->server_type == SILC_ROUTER && 
5211       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5212     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5213                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
5214     goto out;
5215   }
5216
5217   /* Get the remote server */
5218   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5219   if (!host) {
5220     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5221                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5222     goto out;
5223   }
5224
5225   /* Get port */
5226   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5227   if (tmp)
5228     SILC_GET32_MSB(port, tmp);
5229
5230   /* Create the connection. It is done with timeout and is async. */
5231   silc_server_create_connection(server, host, port);
5232
5233   /* Send reply to the sender */
5234   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5235                                         SILC_STATUS_OK);
5236
5237  out:
5238   silc_server_command_free(cmd);
5239 }
5240
5241 /* Server side command of CLOSE. Closes connection to a specified server. */
5242  
5243 SILC_SERVER_CMD_FUNC(close)
5244 {
5245   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5246   SilcServer server = cmd->server;
5247   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5248   SilcServerEntry server_entry;
5249   SilcSocketConnection sock;
5250   unsigned char *tmp;
5251   SilcUInt32 tmp_len;
5252   unsigned char *name;
5253   SilcUInt32 port = SILC_PORT;
5254
5255   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5256
5257   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5258     goto out;
5259
5260   /* Check whether client has the permissions. */
5261   if (client->mode == SILC_UMODE_NONE) {
5262     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5263                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5264     goto out;
5265   }
5266
5267   /* Get the remote server */
5268   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5269   if (!name) {
5270     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5271                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5272     goto out;
5273   }
5274
5275   /* Get port */
5276   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5277   if (tmp)
5278     SILC_GET32_MSB(port, tmp);
5279
5280   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5281                                                  name, port, FALSE, NULL);
5282   if (!server_entry)
5283     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5284                                                    name, port, FALSE, NULL);
5285   if (!server_entry) {
5286     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5287                                           SILC_STATUS_ERR_NO_SERVER_ID);
5288     goto out;
5289   }
5290
5291   /* Send reply to the sender */
5292   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5293                                         SILC_STATUS_OK);
5294
5295   /* Close the connection to the server */
5296   sock = (SilcSocketConnection)server_entry->connection;
5297
5298   /* If we shutdown primary router connection manually then don't trigger
5299      any reconnect or backup router connections, by setting the router
5300      to NULL here. */
5301   if (server->router == server_entry) {
5302     server->id_entry->router = NULL;
5303     server->router = NULL;
5304     server->standalone = TRUE;
5305   }
5306   silc_server_free_sock_user_data(server, sock, NULL);
5307   silc_server_close_connection(server, sock);
5308   
5309  out:
5310   silc_server_command_free(cmd);
5311 }
5312
5313 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5314    active connections. */
5315  
5316 SILC_SERVER_CMD_FUNC(shutdown)
5317 {
5318   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5319   SilcServer server = cmd->server;
5320   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5321
5322   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5323
5324   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5325     goto out;
5326
5327   /* Check whether client has the permission. */
5328   if (client->mode == SILC_UMODE_NONE) {
5329     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5330                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5331     goto out;
5332   }
5333
5334   /* Send reply to the sender */
5335   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5336                                         SILC_STATUS_OK);
5337
5338   /* Then, gracefully, or not, bring the server down. */
5339   silc_server_stop(server);
5340   exit(0);
5341
5342  out:
5343   silc_server_command_free(cmd);
5344 }