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