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, TRUE, 
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
2433     dest_id = silc_id_payload_parse_id(tmp, len);
2434     if (!dest_id) {
2435       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2437       goto out;
2438     }
2439
2440     /* Get the client entry */
2441     dest = silc_server_get_client_resolve(server, dest_id);
2442     if (!dest) {
2443       if (server->server_type != SILC_SERVER) {
2444         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2445                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2446         goto out;
2447       }
2448       
2449       /* The client info is being resolved. Reprocess this packet after
2450          receiving the reply to the query. */
2451       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2452                                   server->cmd_ident,
2453                                   silc_server_command_invite, 
2454                                   silc_server_command_dup(cmd));
2455       cmd->pending = TRUE;
2456       silc_free(channel_id);
2457       silc_free(dest_id);
2458       goto out;
2459     }
2460
2461     /* Check whether the requested client is already on the channel. */
2462     if (silc_server_client_on_channel(dest, channel)) {
2463       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2464                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2465       goto out;
2466     }
2467     
2468     /* Get route to the client */
2469     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2470     if (!dest_sock) {
2471       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2472                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2473       goto out;
2474     }
2475
2476     memset(invite, 0, sizeof(invite));
2477     strncat(invite, dest->nickname, strlen(dest->nickname));
2478     strncat(invite, "!", 1);
2479     strncat(invite, dest->username, strlen(dest->username));
2480     if (!strchr(dest->username, '@')) {
2481       strncat(invite, "@", 1);
2482       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2483     }
2484
2485     len = strlen(invite);
2486     if (!channel->invite_list)
2487       channel->invite_list = silc_calloc(len + 2, 
2488                                          sizeof(*channel->invite_list));
2489     else
2490       channel->invite_list = silc_realloc(channel->invite_list, 
2491                                           sizeof(*channel->invite_list) * 
2492                                           (len + 
2493                                            strlen(channel->invite_list) + 2));
2494     strncat(channel->invite_list, invite, len);
2495     strncat(channel->invite_list, ",", 1);
2496
2497     /* Send notify to the client that is invited to the channel */
2498     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2499     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2500     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2501                                  SILC_ID_CLIENT,
2502                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2503                                  idp->data, idp->len, 
2504                                  channel->channel_name, 
2505                                  strlen(channel->channel_name),
2506                                  idp2->data, idp2->len);
2507     silc_buffer_free(idp);
2508     silc_buffer_free(idp2);
2509   }
2510
2511   /* Add the client to the invite list of the channel */
2512   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2513   if (add) {
2514     if (!channel->invite_list)
2515       channel->invite_list = silc_calloc(len + 2, 
2516                                          sizeof(*channel->invite_list));
2517     else
2518       channel->invite_list = silc_realloc(channel->invite_list, 
2519                                           sizeof(*channel->invite_list) * 
2520                                           (len + 
2521                                            strlen(channel->invite_list) + 2));
2522     if (add[len - 1] == ',')
2523       add[len - 1] = '\0';
2524     
2525     strncat(channel->invite_list, add, len);
2526     strncat(channel->invite_list, ",", 1);
2527   }
2528
2529   /* Get the invite to be removed and remove it from the list */
2530   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2531   if (del && channel->invite_list) {
2532     char *start, *end, *n;
2533
2534     if (!strncmp(channel->invite_list, del, 
2535                  strlen(channel->invite_list) - 1)) {
2536       silc_free(channel->invite_list);
2537       channel->invite_list = NULL;
2538     } else {
2539       start = strstr(channel->invite_list, del);
2540       if (start && strlen(start) >= len) {
2541         end = start + len;
2542         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2543         strncat(n, channel->invite_list, start - channel->invite_list);
2544         strncat(n, end + 1, ((channel->invite_list + 
2545                               strlen(channel->invite_list)) - end) - 1);
2546         silc_free(channel->invite_list);
2547         channel->invite_list = n;
2548       }
2549     }
2550   }
2551
2552   /* Send notify to the primary router */
2553   if (!server->standalone)
2554     silc_server_send_notify_invite(server, server->router->connection,
2555                                    server->server_type == SILC_ROUTER ?
2556                                    TRUE : FALSE, channel,
2557                                    sender->id, add, del);
2558
2559   /* Send command reply */
2560   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2561
2562   if (add || del)
2563     packet = 
2564       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2565                                            SILC_STATUS_OK, ident, 2,
2566                                            2, tmp, len,
2567                                            3, channel->invite_list,
2568                                            channel->invite_list ?
2569                                            strlen(channel->invite_list) : 0);
2570   else
2571     packet = 
2572       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2573                                            SILC_STATUS_OK, ident, 1,
2574                                            2, tmp, len);
2575   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2576                           packet->data, packet->len, FALSE);
2577   silc_buffer_free(packet);
2578
2579  out:
2580   silc_free(dest_id);
2581   silc_free(channel_id);
2582   silc_server_command_free(cmd);
2583 }
2584
2585 typedef struct {
2586   SilcServer server;
2587   SilcSocketConnection sock;
2588   char *signoff;
2589 } *QuitInternal;
2590
2591 /* Quits connection to client. This gets called if client won't
2592    close the connection even when it has issued QUIT command. */
2593
2594 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2595 {
2596   QuitInternal q = (QuitInternal)context;
2597
2598   /* Free all client specific data, such as client entry and entires
2599      on channels this client may be on. */
2600   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2601                                TRUE, q->signoff);
2602   q->sock->user_data = NULL;
2603
2604   /* Close the connection on our side */
2605   silc_server_close_connection(q->server, q->sock);
2606
2607   silc_free(q->signoff);
2608   silc_free(q);
2609 }
2610
2611 /* Quits SILC session. This is the normal way to disconnect client. */
2612  
2613 SILC_SERVER_CMD_FUNC(quit)
2614 {
2615   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2616   SilcServer server = cmd->server;
2617   SilcSocketConnection sock = cmd->sock;
2618   QuitInternal q;
2619   unsigned char *tmp = NULL;
2620   uint32 len = 0;
2621
2622   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2623
2624   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2625     goto out;
2626
2627   /* Get destination ID */
2628   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2629   if (len > 128)
2630     tmp = NULL;
2631
2632   q = silc_calloc(1, sizeof(*q));
2633   q->server = server;
2634   q->sock = sock;
2635   q->signoff = tmp ? strdup(tmp) : NULL;
2636
2637   /* We quit the connection with little timeout */
2638   silc_schedule_task_add(server->schedule, sock->sock,
2639                      silc_server_command_quit_cb, (void *)q,
2640                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2641
2642  out:
2643   silc_server_command_free(cmd);
2644 }
2645
2646 /* Server side of command KILL. This command is used by router operator
2647    to remove an client from the SILC Network temporarily. */
2648
2649 SILC_SERVER_CMD_FUNC(kill)
2650 {
2651   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2652   SilcServer server = cmd->server;
2653   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2654   SilcClientEntry remote_client;
2655   SilcClientID *client_id;
2656   unsigned char *tmp, *comment;
2657   uint32 tmp_len, tmp_len2;
2658
2659   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2660
2661   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2662     goto out;
2663
2664   /* KILL command works only on router */
2665   if (server->server_type != SILC_ROUTER) {
2666     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2667                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2668     goto out;
2669   }
2670
2671   /* Check whether client has the permissions. */
2672   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2673     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2674                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2675     goto out;
2676   }
2677
2678   /* Get the client ID */
2679   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2680   if (!tmp) {
2681     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2682                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2683     goto out;
2684   }
2685   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2686   if (!client_id) {
2687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2689     goto out;
2690   }
2691
2692   /* Get the client entry */
2693   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2694                                                 client_id, TRUE, NULL);
2695   if (!remote_client) {
2696     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2697                                                   client_id, TRUE, NULL);
2698     if (!remote_client) {
2699       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2700                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2701       goto out;
2702     }
2703   }
2704
2705   /* Get comment */
2706   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2707   if (tmp_len2 > 128)
2708     comment = NULL;
2709
2710   /* Send reply to the sender */
2711   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2712                                         SILC_STATUS_OK);
2713
2714   /* Send the KILL notify packets. First send it to the channel, then
2715      to our primary router and then directly to the client who is being
2716      killed right now. */
2717
2718   /* Send KILLED notify to the channels. It is not sent to the client
2719      as it will be sent differently destined directly to the client and not
2720      to the channel. */
2721   silc_server_send_notify_on_channels(server, remote_client, 
2722                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2723                                       comment ? 2 : 1,
2724                                       tmp, tmp_len,
2725                                       comment, comment ? tmp_len2 : 0);
2726
2727   /* Send KILLED notify to primary route */
2728   if (!server->standalone)
2729     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2730                                    remote_client->id, comment);
2731
2732   /* Send KILLED notify to the client directly */
2733   silc_server_send_notify_killed(server, remote_client->connection ? 
2734                                  remote_client->connection : 
2735                                  remote_client->router->connection, FALSE,
2736                                  remote_client->id, comment);
2737
2738   /* Remove the client from all channels. This generates new keys to the
2739      channels as well. */
2740   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2741                                    NULL, TRUE);
2742
2743   /* Remove the client entry, If it is locally connected then we will also
2744      disconnect the client here */
2745   if (remote_client->connection) {
2746     /* Remove locally conneted client */
2747     SilcSocketConnection sock = remote_client->connection;
2748     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2749     silc_server_close_connection(server, sock);
2750   } else {
2751     /* Remove remote client */
2752     if (!silc_idlist_del_client(server->global_list, remote_client))
2753       silc_idlist_del_client(server->local_list, remote_client);
2754   }
2755
2756  out:
2757   silc_server_command_free(cmd);
2758 }
2759
2760 /* Server side of command INFO. This sends information about us to 
2761    the client. If client requested specific server we will send the 
2762    command to that server. */
2763
2764 SILC_SERVER_CMD_FUNC(info)
2765 {
2766   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2767   SilcServer server = cmd->server;
2768   SilcBuffer packet, idp;
2769   unsigned char *tmp;
2770   uint32 tmp_len;
2771   char *dest_server, *server_info = NULL, *server_name;
2772   uint16 ident = silc_command_get_ident(cmd->payload);
2773   SilcServerEntry entry = NULL;
2774   SilcServerID *server_id = NULL;
2775
2776   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2777
2778   /* Get server name */
2779   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2780
2781   /* Get Server ID */
2782   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2783   if (tmp) {
2784     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2785     if (!server_id) {
2786       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2787                                             SILC_STATUS_ERR_NO_SERVER_ID);
2788       goto out;
2789     }
2790   }
2791
2792   if (server_id) {
2793     /* Check whether we have this server cached */
2794     entry = silc_idlist_find_server_by_id(server->local_list,
2795                                           server_id, TRUE, NULL);
2796     if (!entry) {
2797       entry = silc_idlist_find_server_by_id(server->global_list,
2798                                             server_id, TRUE, NULL);
2799       if (!entry && server->server_type != SILC_SERVER) {
2800         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2801                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2802         goto out;
2803       }
2804     }
2805   }
2806
2807   /* Some buggy servers has sent request to router about themselves. */
2808   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2809     goto out;
2810
2811   if ((!dest_server && !server_id && !entry) || (entry && 
2812                                                  entry == server->id_entry) ||
2813       (dest_server && !cmd->pending && 
2814        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2815     /* Send our reply */
2816     char info_string[256];
2817
2818     memset(info_string, 0, sizeof(info_string));
2819     snprintf(info_string, sizeof(info_string), 
2820              "location: %s server: %s admin: %s <%s>",
2821              server->config->admin_info->location,
2822              server->config->admin_info->server_type,
2823              server->config->admin_info->admin_name,
2824              server->config->admin_info->admin_email);
2825
2826     server_info = info_string;
2827     entry = server->id_entry;
2828   } else {
2829     /* Check whether we have this server cached */
2830     if (!entry && dest_server) {
2831       entry = silc_idlist_find_server_by_name(server->global_list,
2832                                               dest_server, TRUE, NULL);
2833       if (!entry) {
2834         entry = silc_idlist_find_server_by_name(server->local_list,
2835                                                 dest_server, TRUE, NULL);
2836       }
2837     }
2838
2839     if (!cmd->pending &&
2840         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2841       /* Send to the server */
2842       SilcBuffer tmpbuf;
2843       uint16 old_ident;
2844
2845       old_ident = silc_command_get_ident(cmd->payload);
2846       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2847       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2848
2849       silc_server_packet_send(server, entry->connection,
2850                               SILC_PACKET_COMMAND, cmd->packet->flags,
2851                               tmpbuf->data, tmpbuf->len, TRUE);
2852
2853       /* Reprocess this packet after received reply from router */
2854       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2855                                   silc_command_get_ident(cmd->payload),
2856                                   silc_server_command_info,
2857                                   silc_server_command_dup(cmd));
2858       cmd->pending = TRUE;
2859       silc_command_set_ident(cmd->payload, old_ident);
2860       silc_buffer_free(tmpbuf);
2861       goto out;
2862     }
2863
2864     if (!entry && !cmd->pending && !server->standalone) {
2865       /* Send to the primary router */
2866       SilcBuffer tmpbuf;
2867       uint16 old_ident;
2868
2869       old_ident = silc_command_get_ident(cmd->payload);
2870       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2871       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2872
2873       silc_server_packet_send(server, server->router->connection,
2874                               SILC_PACKET_COMMAND, cmd->packet->flags,
2875                               tmpbuf->data, tmpbuf->len, TRUE);
2876
2877       /* Reprocess this packet after received reply from router */
2878       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2879                                   silc_command_get_ident(cmd->payload),
2880                                   silc_server_command_info,
2881                                   silc_server_command_dup(cmd));
2882       cmd->pending = TRUE;
2883       silc_command_set_ident(cmd->payload, old_ident);
2884       silc_buffer_free(tmpbuf);
2885       goto out;
2886     }
2887   }
2888
2889   silc_free(server_id);
2890
2891   if (!entry) {
2892     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2893                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2894     goto out;
2895   }
2896
2897   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2898   if (!server_info)
2899     server_info = entry->server_info;
2900   server_name = entry->server_name;
2901
2902   /* Send the reply */
2903   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2904                                                 SILC_STATUS_OK, ident, 3,
2905                                                 2, idp->data, idp->len,
2906                                                 3, server_name, 
2907                                                 strlen(server_name),
2908                                                 4, server_info, 
2909                                                 server_info ? 
2910                                                 strlen(server_info) : 0);
2911   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2912                           packet->data, packet->len, FALSE);
2913     
2914   silc_buffer_free(packet);
2915   silc_buffer_free(idp);
2916
2917  out:
2918   silc_server_command_free(cmd);
2919 }
2920
2921 /* Server side of command PING. This just replies to the ping. */
2922
2923 SILC_SERVER_CMD_FUNC(ping)
2924 {
2925   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2926   SilcServer server = cmd->server;
2927   SilcServerID *id;
2928   uint32 len;
2929   unsigned char *tmp;
2930
2931   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2932
2933   /* Get Server ID */
2934   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2935   if (!tmp) {
2936     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2937                                           SILC_STATUS_ERR_NO_SERVER_ID);
2938     goto out;
2939   }
2940   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2941   if (!id)
2942     goto out;
2943
2944   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2945     /* Send our reply */
2946     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2947                                           SILC_STATUS_OK);
2948   } else {
2949     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2950                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2951     goto out;
2952   }
2953
2954   silc_free(id);
2955
2956  out:
2957   silc_server_command_free(cmd);
2958 }
2959
2960 /* Internal routine to join channel. The channel sent to this function
2961    has been either created or resolved from ID lists. This joins the sent
2962    client to the channel. */
2963
2964 static void silc_server_command_join_channel(SilcServer server, 
2965                                              SilcServerCommandContext cmd,
2966                                              SilcChannelEntry channel,
2967                                              SilcClientID *client_id,
2968                                              bool created,
2969                                              bool create_key,
2970                                              uint32 umode,
2971                                              const unsigned char *auth,
2972                                              uint32 auth_len)
2973 {
2974   SilcSocketConnection sock = cmd->sock;
2975   unsigned char *tmp;
2976   uint32 tmp_len, user_count;
2977   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2978   SilcClientEntry client;
2979   SilcChannelClientEntry chl;
2980   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2981   uint16 ident = silc_command_get_ident(cmd->payload);
2982   char check[512], check2[512];
2983   bool founder = FALSE;
2984
2985   SILC_LOG_DEBUG(("Start"));
2986
2987   if (!channel)
2988     return;
2989
2990   /* Get the client entry */
2991   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2992     client = (SilcClientEntry)sock->user_data;
2993   } else {
2994     client = silc_server_get_client_resolve(server, client_id);
2995     if (!client) {
2996       if (cmd->pending)
2997         goto out;
2998
2999       /* The client info is being resolved. Reprocess this packet after
3000          receiving the reply to the query. */
3001       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3002                                   server->cmd_ident,
3003                                   silc_server_command_join, 
3004                                   silc_server_command_dup(cmd));
3005       cmd->pending = TRUE;
3006       goto out;
3007     }
3008
3009     cmd->pending = FALSE;
3010   }
3011
3012   /*
3013    * Check founder auth payload if provided.  If client can gain founder
3014    * privileges it can override various conditions on joining the channel,
3015    * and can have directly the founder mode set on the channel.
3016    */
3017   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3018     SilcIDListData idata = (SilcIDListData)client;
3019
3020     if (channel->founder_key && idata->public_key &&
3021         silc_pkcs_public_key_compare(channel->founder_key, 
3022                                      idata->public_key)) {
3023       void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3024                          (void *)channel->founder_passwd : 
3025                          (void *)channel->founder_key);
3026       uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3027                               channel->founder_passwd_len : 0);
3028
3029       /* Check whether the client is to become founder */
3030       if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
3031                                 auth_data, auth_data_len,
3032                                 idata->hash, client->id, SILC_ID_CLIENT)) {
3033         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3034         founder = TRUE;
3035       }
3036     }
3037   }
3038
3039   /*
3040    * Check channel modes
3041    */
3042
3043   if (!umode) {
3044     memset(check, 0, sizeof(check));
3045     memset(check2, 0, sizeof(check2));
3046     strncat(check, client->nickname, strlen(client->nickname));
3047     strncat(check, "!", 1);
3048     strncat(check, client->username, strlen(client->username));
3049     if (!strchr(client->username, '@')) {
3050       strncat(check, "@", 1);
3051       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3052     }
3053
3054     strncat(check2, client->nickname, strlen(client->nickname));
3055     if (!strchr(client->nickname, '@')) {
3056       strncat(check2, "@", 1);
3057       strncat(check2, server->server_name, strlen(server->server_name));
3058     }
3059     strncat(check2, "!", 1);
3060     strncat(check2, client->username, strlen(client->username));
3061     if (!strchr(client->username, '@')) {
3062       strncat(check2, "@", 1);
3063       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3064     }
3065     
3066     /* Check invite list if channel is invite-only channel */
3067     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3068       if (!channel->invite_list ||
3069           (!silc_string_match(channel->invite_list, check) &&
3070            !silc_string_match(channel->invite_list, check2))) {
3071         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3072                                               SILC_STATUS_ERR_NOT_INVITED);
3073         goto out;
3074       }
3075     }
3076
3077     /* Check ban list if it exists. If the client's nickname, server,
3078        username and/or hostname is in the ban list the access to the
3079        channel is denied. */
3080     if (channel->ban_list) {
3081       if (silc_string_match(channel->ban_list, check) ||
3082           silc_string_match(channel->ban_list, check2)) {
3083         silc_server_command_send_status_reply(
3084                                       cmd, SILC_COMMAND_JOIN,
3085                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3086         goto out;
3087       }
3088     }
3089     
3090     /* Check user count limit if set. */
3091     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3092       if (silc_hash_table_count(channel->user_list) + 1 > 
3093           channel->user_limit) {
3094         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3095                                               SILC_STATUS_ERR_CHANNEL_IS_FULL);
3096         goto out;
3097       }
3098     }
3099   }
3100
3101   /* Check the channel passphrase if set. */
3102   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3103     /* Get passphrase */
3104     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3105     if (tmp) {
3106       passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3107       memcpy(passphrase, tmp, tmp_len);
3108     }
3109   
3110     if (!passphrase || !channel->passphrase ||
3111         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3112       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3113                                             SILC_STATUS_ERR_BAD_PASSWORD);
3114       goto out;
3115     }
3116   }
3117
3118   /*
3119    * Client is allowed to join to the channel. Make it happen.
3120    */
3121
3122   /* Check whether the client already is on the channel */
3123   if (silc_server_client_on_channel(client, channel)) {
3124     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3125                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3126     goto out;
3127   }
3128
3129   /* Generate new channel key as protocol dictates */
3130   if (create_key) {
3131     if (!silc_server_create_channel_key(server, channel, 0))
3132       goto out;
3133
3134     /* Send the channel key. This is broadcasted to the channel but is not
3135        sent to the client who is joining to the channel. */
3136     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3137       silc_server_send_channel_key(server, NULL, channel, 
3138                                    server->server_type == SILC_ROUTER ? 
3139                                    FALSE : !server->standalone);
3140   }
3141
3142   /* Join the client to the channel by adding it to channel's user list.
3143      Add also the channel to client entry's channels list for fast cross-
3144      referencing. */
3145   chl = silc_calloc(1, sizeof(*chl));
3146   chl->mode = umode;
3147   chl->client = client;
3148   chl->channel = channel;
3149   silc_hash_table_add(channel->user_list, client, chl);
3150   silc_hash_table_add(client->channels, channel, chl);
3151
3152   /* Get users on the channel */
3153   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3154                                    &user_count);
3155
3156   /* Encode Client ID Payload of the original client who wants to join */
3157   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3158
3159   /* Encode command reply packet */
3160   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3161   SILC_PUT32_MSB(channel->mode, mode);
3162   SILC_PUT32_MSB(created, tmp2);
3163   SILC_PUT32_MSB(user_count, tmp3);
3164
3165   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3166     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3167     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3168                                            strlen(channel->channel_key->
3169                                                   cipher->name),
3170                                            channel->channel_key->cipher->name,
3171                                            channel->key_len / 8, channel->key);
3172     silc_free(tmp);
3173   }
3174
3175   reply = 
3176     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3177                                          SILC_STATUS_OK, ident, 13,
3178                                          2, channel->channel_name,
3179                                          strlen(channel->channel_name),
3180                                          3, chidp->data, chidp->len,
3181                                          4, clidp->data, clidp->len,
3182                                          5, mode, 4,
3183                                          6, tmp2, 4,
3184                                          7, keyp ? keyp->data : NULL, 
3185                                          keyp ? keyp->len : 0,
3186                                          8, channel->ban_list, 
3187                                          channel->ban_list ?
3188                                          strlen(channel->ban_list) : 0,
3189                                          9, channel->invite_list,
3190                                          channel->invite_list ?
3191                                          strlen(channel->invite_list) : 0,
3192                                          10, channel->topic,
3193                                          channel->topic ?
3194                                          strlen(channel->topic) : 0,
3195                                          11, silc_hmac_get_name(channel->hmac),
3196                                          strlen(silc_hmac_get_name(channel->
3197                                                                    hmac)),
3198                                          12, tmp3, 4,
3199                                          13, user_list->data, user_list->len,
3200                                          14, mode_list->data, 
3201                                          mode_list->len);
3202
3203   /* Send command reply */
3204   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3205                           reply->data, reply->len, FALSE);
3206
3207   /* Send JOIN notify to locally connected clients on the channel. If
3208      we are normal server then router will send or have sent JOIN notify
3209      already. However since we've added the client already to our channel
3210      we'll ignore it (in packet_receive.c) so we must send it here. If
3211      we are router then this will send it to local clients and local
3212      servers. */
3213   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3214                                      SILC_NOTIFY_TYPE_JOIN, 2,
3215                                      clidp->data, clidp->len,
3216                                      chidp->data, chidp->len);
3217
3218   if (!cmd->pending) {
3219     /* Send JOIN notify packet to our primary router */
3220     if (!server->standalone)
3221       silc_server_send_notify_join(server, server->router->connection,
3222                                    server->server_type == SILC_ROUTER ?
3223                                    TRUE : FALSE, channel, client->id);
3224
3225     if (keyp)
3226       /* Distribute the channel key to all backup routers. */
3227       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3228                               keyp->data, keyp->len, FALSE, TRUE);
3229
3230     /* If client became founder by providing correct founder auth data
3231        notify the mode change to the channel. */
3232     if (founder) {
3233       SILC_PUT32_MSB(chl->mode, mode);
3234       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3235                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3236                                          clidp->data, clidp->len,
3237                                          mode, 4, clidp->data, clidp->len);
3238       
3239       /* Set CUMODE notify type to network */
3240       if (!server->standalone)
3241         silc_server_send_notify_cumode(server, server->router->connection,
3242                                        server->server_type == SILC_ROUTER ? 
3243                                        TRUE : FALSE, channel,
3244                                        chl->mode, client->id, SILC_ID_CLIENT,
3245                                        client->id);
3246     }
3247   }
3248
3249   silc_buffer_free(reply);
3250   silc_buffer_free(clidp);
3251   silc_buffer_free(chidp);
3252   silc_buffer_free(keyp);
3253   silc_buffer_free(user_list);
3254   silc_buffer_free(mode_list);
3255
3256  out:
3257   silc_free(passphrase);
3258 }
3259
3260 /* Server side of command JOIN. Joins client into requested channel. If 
3261    the channel does not exist it will be created. */
3262
3263 SILC_SERVER_CMD_FUNC(join)
3264 {
3265   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3266   SilcServer server = cmd->server;
3267   unsigned char *auth;
3268   uint32 tmp_len, auth_len;
3269   char *tmp, *channel_name = NULL, *cipher, *hmac;
3270   SilcChannelEntry channel;
3271   uint32 umode = 0;
3272   bool created = FALSE, create_key = TRUE;
3273   SilcClientID *client_id;
3274
3275   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3276
3277   /* Get channel name */
3278   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3279   if (!tmp) {
3280     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3281                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3282     goto out;
3283   }
3284   channel_name = tmp;
3285
3286   if (tmp_len > 256)
3287     channel_name[255] = '\0';
3288
3289   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3290     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3291                                           SILC_STATUS_ERR_BAD_CHANNEL);
3292     goto out;
3293   }
3294
3295   /* Get Client ID of the client who is joining to the channel */
3296   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3297   if (!tmp) {
3298     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3299                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3300     goto out;
3301   }
3302   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3303   if (!client_id) {
3304     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3305                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3306     goto out;
3307   }
3308
3309   /* Get cipher, hmac name and auth payload */
3310   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3311   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3312   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3313
3314   /* See if the channel exists */
3315   channel = silc_idlist_find_channel_by_name(server->local_list, 
3316                                              channel_name, NULL);
3317
3318   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3319     /* If this is coming from client the Client ID in the command packet must
3320        be same as the client's ID. */
3321     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3322       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3323       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3324         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3325                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3326         goto out;
3327       }
3328     }
3329
3330     if (!channel || channel->disabled) {
3331       /* Channel not found */
3332
3333       /* If we are standalone server we don't have a router, we just create 
3334          the channel by ourselves. */
3335       if (server->standalone) {
3336         channel = silc_server_create_new_channel(server, server->id, cipher, 
3337                                                  hmac, channel_name, TRUE);
3338         if (!channel) {
3339           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3340                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3341           goto out;
3342         }
3343         
3344         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3345         created = TRUE;
3346         create_key = FALSE;
3347         
3348       } else {
3349
3350         /* The channel does not exist on our server. If we are normal server 
3351            we will send JOIN command to our router which will handle the
3352            joining procedure (either creates the channel if it doesn't exist 
3353            or joins the client to it). */
3354         if (server->server_type != SILC_ROUTER) {
3355           SilcBuffer tmpbuf;
3356           uint16 old_ident;
3357
3358           /* If this is pending command callback then we've resolved
3359              it and it didn't work, return since we've notified the
3360              client already in the command reply callback. */
3361           if (cmd->pending)
3362             goto out;
3363           
3364           old_ident = silc_command_get_ident(cmd->payload);
3365           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3366           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3367           
3368           /* Send JOIN command to our router */
3369           silc_server_packet_send(server, (SilcSocketConnection)
3370                                   server->router->connection,
3371                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3372                                   tmpbuf->data, tmpbuf->len, TRUE);
3373           
3374           /* Reprocess this packet after received reply from router */
3375           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3376                                       silc_command_get_ident(cmd->payload),
3377                                       silc_server_command_join,
3378                                       silc_server_command_dup(cmd));
3379           cmd->pending = TRUE;
3380           goto out;
3381         }
3382         
3383         /* We are router and the channel does not seem exist so we will check
3384            our global list as well for the channel. */
3385         channel = silc_idlist_find_channel_by_name(server->global_list, 
3386                                                    channel_name, NULL);
3387         if (!channel) {
3388           /* Channel really does not exist, create it */
3389           channel = silc_server_create_new_channel(server, server->id, cipher, 
3390                                                    hmac, channel_name, TRUE);
3391           if (!channel) {
3392             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3393                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3394             goto out;
3395           }
3396
3397           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3398           created = TRUE;
3399           create_key = FALSE;
3400         }
3401       }
3402     }
3403   } else {
3404     if (!channel) {
3405       /* Channel not found */
3406
3407       /* If the command came from router and we are normal server then
3408          something went wrong with the joining as the channel was not found.
3409          We can't do anything else but ignore this. */
3410       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3411           server->server_type != SILC_ROUTER)
3412         goto out;
3413       
3414       /* We are router and the channel does not seem exist so we will check
3415          our global list as well for the channel. */
3416       channel = silc_idlist_find_channel_by_name(server->global_list, 
3417                                                  channel_name, NULL);
3418       if (!channel) {
3419         /* Channel really does not exist, create it */
3420         channel = silc_server_create_new_channel(server, server->id, cipher, 
3421                                                  hmac, channel_name, TRUE);
3422         if (!channel) {
3423           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3424                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3425           goto out;
3426         }
3427
3428         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3429         created = TRUE;
3430         create_key = FALSE;
3431       }
3432     }
3433   }
3434
3435   /* Check whether the channel was created by our router */
3436   if (cmd->pending && context2) {
3437     SilcServerCommandReplyContext reply = 
3438       (SilcServerCommandReplyContext)context2;
3439
3440     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3441       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3442       SILC_GET32_MSB(created, tmp);
3443       create_key = FALSE;       /* Router returned the key already */
3444     }
3445
3446     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3447       created = TRUE;
3448   }
3449
3450   /* If the channel does not have global users and is also empty the client
3451      will be the channel founder and operator. */
3452   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3453     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3454
3455   /* Join to the channel */
3456   silc_server_command_join_channel(server, cmd, channel, client_id,
3457                                    created, create_key, umode,
3458                                    auth, auth_len);
3459
3460   silc_free(client_id);
3461
3462  out:
3463   silc_server_command_free(cmd);
3464 }
3465
3466 /* Server side of command MOTD. Sends server's current "message of the
3467    day" to the client. */
3468
3469 SILC_SERVER_CMD_FUNC(motd)
3470 {
3471   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3472   SilcServer server = cmd->server;
3473   SilcBuffer packet, idp;
3474   char *motd, *dest_server;
3475   uint32 motd_len;
3476   uint16 ident = silc_command_get_ident(cmd->payload);
3477   
3478   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3479
3480   /* Get server name */
3481   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3482   if (!dest_server) {
3483     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3484                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3485     goto out;
3486   }
3487
3488   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3489     /* Send our MOTD */
3490
3491     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3492
3493     if (server->config && server->config->motd && 
3494         server->config->motd->motd_file) {
3495       /* Send motd */
3496       motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3497       if (!motd)
3498         goto out;
3499       
3500       motd[motd_len] = 0;
3501       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3502                                                     SILC_STATUS_OK, ident, 2,
3503                                                     2, idp, idp->len,
3504                                                     3, motd, motd_len);
3505     } else {
3506       /* No motd */
3507       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3508                                                     SILC_STATUS_OK, ident, 1,
3509                                                     2, idp, idp->len);
3510     }
3511
3512     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3513                             packet->data, packet->len, FALSE);
3514     silc_buffer_free(packet);
3515     silc_buffer_free(idp);
3516   } else {
3517     SilcServerEntry entry;
3518
3519     /* Check whether we have this server cached */
3520     entry = silc_idlist_find_server_by_name(server->global_list,
3521                                             dest_server, TRUE, NULL);
3522     if (!entry) {
3523       entry = silc_idlist_find_server_by_name(server->local_list,
3524                                               dest_server, TRUE, NULL);
3525     }
3526
3527     if (server->server_type != SILC_SERVER && !cmd->pending && 
3528         entry && !entry->motd) {
3529       /* Send to the server */
3530       SilcBuffer tmpbuf;
3531       uint16 old_ident;
3532
3533       old_ident = silc_command_get_ident(cmd->payload);
3534       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3535       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3536
3537       silc_server_packet_send(server, entry->connection,
3538                               SILC_PACKET_COMMAND, cmd->packet->flags,
3539                               tmpbuf->data, tmpbuf->len, TRUE);
3540
3541       /* Reprocess this packet after received reply from router */
3542       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3543                                   silc_command_get_ident(cmd->payload),
3544                                   silc_server_command_motd,
3545                                   silc_server_command_dup(cmd));
3546       cmd->pending = TRUE;
3547       silc_command_set_ident(cmd->payload, old_ident);
3548       silc_buffer_free(tmpbuf);
3549       goto out;
3550     }
3551
3552     if (!entry && !cmd->pending && !server->standalone) {
3553       /* Send to the primary router */
3554       SilcBuffer tmpbuf;
3555       uint16 old_ident;
3556
3557       old_ident = silc_command_get_ident(cmd->payload);
3558       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3559       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3560
3561       silc_server_packet_send(server, server->router->connection,
3562                               SILC_PACKET_COMMAND, cmd->packet->flags,
3563                               tmpbuf->data, tmpbuf->len, TRUE);
3564
3565       /* Reprocess this packet after received reply from router */
3566       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3567                                   silc_command_get_ident(cmd->payload),
3568                                   silc_server_command_motd,
3569                                   silc_server_command_dup(cmd));
3570       cmd->pending = TRUE;
3571       silc_command_set_ident(cmd->payload, old_ident);
3572       silc_buffer_free(tmpbuf);
3573       goto out;
3574     }
3575
3576     if (!entry) {
3577       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3578                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3579       goto out;
3580     }
3581
3582     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3583     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3584                                                   SILC_STATUS_OK, ident, 2,
3585                                                   2, idp, idp->len,
3586                                                   3, entry->motd,
3587                                                   entry->motd ? 
3588                                                   strlen(entry->motd) : 0);
3589     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3590                             packet->data, packet->len, FALSE);
3591     silc_buffer_free(packet);
3592     silc_buffer_free(idp);
3593   }
3594
3595  out:
3596   silc_server_command_free(cmd);
3597 }
3598
3599 /* Server side of command UMODE. Client can use this command to set/unset
3600    user mode. Client actually cannot set itself to be as server/router
3601    operator so this can be used only to unset the modes. */
3602
3603 SILC_SERVER_CMD_FUNC(umode)
3604 {
3605   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3606   SilcServer server = cmd->server;
3607   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3608   SilcBuffer packet;
3609   unsigned char *tmp_mask;
3610   uint32 mask;
3611   uint16 ident = silc_command_get_ident(cmd->payload);
3612
3613   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3614     goto out;
3615
3616   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3617
3618   /* Get the client's mode mask */
3619   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3620   if (!tmp_mask) {
3621     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3622                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3623     goto out;
3624   }
3625   SILC_GET32_MSB(mask, tmp_mask);
3626
3627   /* 
3628    * Change the mode 
3629    */
3630
3631   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3632     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3633       /* Cannot operator mode */
3634       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3635                                             SILC_STATUS_ERR_PERM_DENIED);
3636       goto out;
3637     }
3638   } else {
3639     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3640       /* Remove the server operator rights */
3641       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3642   }
3643
3644   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3645     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3646       /* Cannot operator mode */
3647       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3648                                             SILC_STATUS_ERR_PERM_DENIED);
3649       goto out;
3650     }
3651   } else {
3652     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3653       /* Remove the router operator rights */
3654       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3655   }
3656
3657   if (mask & SILC_UMODE_GONE) {
3658     client->mode |= SILC_UMODE_GONE;
3659   } else {
3660     if (client->mode & SILC_UMODE_GONE)
3661       /* Remove the gone status */
3662       client->mode &= ~SILC_UMODE_GONE;
3663   }
3664
3665   /* Send UMODE change to primary router */
3666   if (!server->standalone)
3667     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3668                                   client->id, client->mode);
3669
3670   /* Send command reply to sender */
3671   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3672                                                 SILC_STATUS_OK, ident, 1,
3673                                                 2, tmp_mask, 4);
3674   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3675                           packet->data, packet->len, FALSE);
3676   silc_buffer_free(packet);
3677
3678  out:
3679   silc_server_command_free(cmd);
3680 }
3681
3682 /* Checks that client has rights to add or remove channel modes. If any
3683    of the checks fails FALSE is returned. */
3684
3685 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3686                                    SilcChannelClientEntry client,
3687                                    uint32 mode)
3688 {
3689   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3690   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3691
3692   /* Check whether has rights to change anything */
3693   if (!is_op && !is_fo)
3694     return FALSE;
3695
3696   /* Check whether has rights to change everything */
3697   if (is_op && is_fo)
3698     return TRUE;
3699
3700   /* We know that client is channel operator, check that they are not
3701      changing anything that requires channel founder rights. Rest of the
3702      modes are available automatically for channel operator. */
3703
3704   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3705     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3706       if (is_op && !is_fo)
3707         return FALSE;
3708   } else {
3709     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3710       if (is_op && !is_fo)
3711         return FALSE;
3712     }
3713   }
3714   
3715   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3716     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3717       if (is_op && !is_fo)
3718         return FALSE;
3719   } else {
3720     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3721       if (is_op && !is_fo)
3722         return FALSE;
3723     }
3724   }
3725
3726   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3727     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3728       if (is_op && !is_fo)
3729         return FALSE;
3730   } else {
3731     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3732       if (is_op && !is_fo)
3733         return FALSE;
3734     }
3735   }
3736   
3737   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3738     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3739       if (is_op && !is_fo)
3740         return FALSE;
3741   } else {
3742     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3743       if (is_op && !is_fo)
3744         return FALSE;
3745     }
3746   }
3747   
3748   return TRUE;
3749 }
3750
3751 /* Server side command of CMODE. Changes channel mode */
3752
3753 SILC_SERVER_CMD_FUNC(cmode)
3754 {
3755   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3756   SilcServer server = cmd->server;
3757   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3758   SilcIDListData idata = (SilcIDListData)client;
3759   SilcChannelID *channel_id;
3760   SilcChannelEntry channel;
3761   SilcChannelClientEntry chl;
3762   SilcBuffer packet, cidp;
3763   unsigned char *tmp, *tmp_id, *tmp_mask;
3764   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3765   uint32 mode_mask, tmp_len, tmp_len2;
3766   uint16 ident = silc_command_get_ident(cmd->payload);
3767
3768   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3769
3770   /* Get Channel ID */
3771   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3772   if (!tmp_id) {
3773     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3774                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3775     goto out;
3776   }
3777   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3778   if (!channel_id) {
3779     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3780                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3781     goto out;
3782   }
3783
3784   /* Get the channel mode mask */
3785   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3786   if (!tmp_mask) {
3787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3789     goto out;
3790   }
3791   SILC_GET32_MSB(mode_mask, tmp_mask);
3792
3793   /* Get channel entry */
3794   channel = silc_idlist_find_channel_by_id(server->local_list, 
3795                                            channel_id, NULL);
3796   if (!channel) {
3797     channel = silc_idlist_find_channel_by_id(server->global_list, 
3798                                              channel_id, NULL);
3799     if (!channel) {
3800       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3801                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3802       goto out;
3803     }
3804   }
3805
3806   /* Check whether this client is on the channel */
3807   if (!silc_server_client_on_channel(client, channel)) {
3808     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3809                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3810     goto out;
3811   }
3812
3813   /* Get entry to the channel user list */
3814   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3815
3816   /* Check that client has rights to change any requested channel modes */
3817   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3818     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3819                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3820     goto out;
3821   }
3822
3823   /*
3824    * Check the modes. Modes that requires nothing special operation are
3825    * not checked here.
3826    */
3827
3828   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3829     /* Channel uses private keys to protect traffic. Client(s) has set the
3830        key locally they want to use, server does not know that key. */
3831     /* Nothing interesting to do here */
3832   } else {
3833     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3834       /* The mode is removed and we need to generate and distribute
3835          new channel key. Clients are not using private channel keys
3836          anymore after this. */
3837
3838       /* Re-generate channel key */
3839       if (!silc_server_create_channel_key(server, channel, 0))
3840         goto out;
3841       
3842       /* Send the channel key. This sends it to our local clients and if
3843          we are normal server to our router as well. */
3844       silc_server_send_channel_key(server, NULL, channel, 
3845                                    server->server_type == SILC_ROUTER ? 
3846                                    FALSE : !server->standalone);
3847
3848       cipher = channel->channel_key->cipher->name;
3849       hmac = (char *)silc_hmac_get_name(channel->hmac);
3850     }
3851   }
3852   
3853   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3854     /* User limit is set on channel */
3855     uint32 user_limit;
3856       
3857     /* Get user limit */
3858     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3859     if (!tmp) {
3860       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3861         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3862                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3863         goto out;
3864       }
3865     } else {
3866       SILC_GET32_MSB(user_limit, tmp);
3867       channel->user_limit = user_limit;
3868     }
3869   } else {
3870     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3871       /* User limit mode is unset. Remove user limit */
3872       channel->user_limit = 0;
3873   }
3874
3875   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3876     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3877       /* Passphrase has been set to channel */
3878       
3879       /* Get the passphrase */
3880       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3881       if (!tmp) {
3882         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3883                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3884         goto out;
3885       }
3886
3887       /* Save the passphrase */
3888       passphrase = channel->passphrase = strdup(tmp);
3889     }
3890   } else {
3891     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3892       /* Passphrase mode is unset. remove the passphrase */
3893       if (channel->passphrase) {
3894         silc_free(channel->passphrase);
3895         channel->passphrase = NULL;
3896       }
3897     }
3898   }
3899
3900   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3901     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3902       /* Cipher to use protect the traffic */
3903       SilcCipher newkey, oldkey;
3904
3905       /* Get cipher */
3906       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3907       if (!cipher) {
3908         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3910         goto out;
3911       }
3912
3913       /* Delete old cipher and allocate the new one */
3914       if (!silc_cipher_alloc(cipher, &newkey)) {
3915         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3917         goto out;
3918       }
3919
3920       oldkey = channel->channel_key;
3921       channel->channel_key = newkey;
3922
3923       /* Re-generate channel key */
3924       if (!silc_server_create_channel_key(server, channel, 0)) {
3925         /* We don't have new key, revert to old one */
3926         channel->channel_key = oldkey;
3927         goto out;
3928       }
3929
3930       /* Remove old channel key for good */
3931       silc_cipher_free(oldkey);
3932
3933       /* Send the channel key. This sends it to our local clients and if
3934          we are normal server to our router as well. */
3935       silc_server_send_channel_key(server, NULL, channel, 
3936                                    server->server_type == SILC_ROUTER ? 
3937                                    FALSE : !server->standalone);
3938     }
3939   } else {
3940     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3941       /* Cipher mode is unset. Remove the cipher and revert back to 
3942          default cipher */
3943       SilcCipher newkey, oldkey;
3944       cipher = channel->cipher;
3945
3946       /* Delete old cipher and allocate default one */
3947       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3948         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3949                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3950         goto out;
3951       }
3952
3953       oldkey = channel->channel_key;
3954       channel->channel_key = newkey;
3955
3956       /* Re-generate channel key */
3957       if (!silc_server_create_channel_key(server, channel, 0)) {
3958         /* We don't have new key, revert to old one */
3959         channel->channel_key = oldkey;
3960         goto out;
3961       }
3962       
3963       /* Remove old channel key for good */
3964       silc_cipher_free(oldkey);
3965
3966       /* Send the channel key. This sends it to our local clients and if
3967          we are normal server to our router as well. */
3968       silc_server_send_channel_key(server, NULL, channel, 
3969                                    server->server_type == SILC_ROUTER ? 
3970                                    FALSE : !server->standalone);
3971     }
3972   }
3973
3974   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3975     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3976       /* HMAC to use protect the traffic */
3977       unsigned char hash[32];
3978       SilcHmac newhmac;
3979
3980       /* Get hmac */
3981       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3982       if (!hmac) {
3983         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3984                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3985         goto out;
3986       }
3987
3988       /* Delete old hmac and allocate the new one */
3989       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3990         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3991                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3992         goto out;
3993       }
3994
3995       silc_hmac_free(channel->hmac);
3996       channel->hmac = newhmac;
3997
3998       /* Set the HMAC key out of current channel key. The client must do
3999          this locally. */
4000       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4001                      channel->key_len / 8, hash);
4002       silc_hmac_set_key(channel->hmac, hash, 
4003                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4004       memset(hash, 0, sizeof(hash));
4005     }
4006   } else {
4007     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4008       /* Hmac mode is unset. Remove the hmac and revert back to 
4009          default hmac */
4010       SilcHmac newhmac;
4011       unsigned char hash[32];
4012       hmac = channel->hmac_name;
4013
4014       /* Delete old hmac and allocate default one */
4015       silc_hmac_free(channel->hmac);
4016       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4017         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4018                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4019         goto out;
4020       }
4021
4022       silc_hmac_free(channel->hmac);
4023       channel->hmac = newhmac;
4024
4025       /* Set the HMAC key out of current channel key. The client must do
4026          this locally. */
4027       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4028                      channel->key_len / 8, 
4029                      hash);
4030       silc_hmac_set_key(channel->hmac, hash, 
4031                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4032       memset(hash, 0, sizeof(hash));
4033     }
4034   }
4035
4036   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4037     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4038       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4039         /* Set the founder authentication */
4040         SilcAuthPayload auth;
4041         
4042         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4043         if (!tmp) {
4044           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4045                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4046           goto out;
4047         }
4048
4049         auth = silc_auth_payload_parse(tmp, tmp_len);
4050         if (!auth) {
4051           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4052                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4053           goto out;
4054         }
4055
4056         /* Save the public key */
4057         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4058         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4059         silc_free(tmp);
4060         
4061         channel->founder_method = silc_auth_get_method(auth);
4062
4063         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4064           tmp = silc_auth_get_data(auth, &tmp_len);
4065           channel->founder_passwd = 
4066             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4067           memcpy(channel->founder_passwd, tmp, tmp_len);
4068           channel->founder_passwd_len = tmp_len;
4069         } else {
4070           /* Verify the payload before setting the mode */
4071           if (!silc_auth_verify(auth, channel->founder_method, 
4072                                 channel->founder_key, 0, idata->hash,
4073                                 client->id, SILC_ID_CLIENT)) {
4074             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4075                                                   SILC_STATUS_ERR_AUTH_FAILED);
4076             goto out;
4077           }
4078         }
4079
4080         silc_auth_payload_free(auth);
4081       }
4082     }
4083   } else {
4084     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4085       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4086         if (channel->founder_key)
4087           silc_pkcs_public_key_free(channel->founder_key);
4088         if (channel->founder_passwd) {
4089           silc_free(channel->founder_passwd);
4090           channel->founder_passwd = NULL;
4091         }
4092       }
4093     }
4094   }
4095
4096   /* Finally, set the mode */
4097   channel->mode = mode_mask;
4098
4099   /* Send CMODE_CHANGE notify. */
4100   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4101   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4102                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4103                                      cidp->data, cidp->len, 
4104                                      tmp_mask, 4,
4105                                      cipher, cipher ? strlen(cipher) : 0,
4106                                      hmac, hmac ? strlen(hmac) : 0,
4107                                      passphrase, passphrase ? 
4108                                      strlen(passphrase) : 0);
4109
4110   /* Set CMODE notify type to network */
4111   if (!server->standalone)
4112     silc_server_send_notify_cmode(server, server->router->connection,
4113                                   server->server_type == SILC_ROUTER ? 
4114                                   TRUE : FALSE, channel,
4115                                   mode_mask, client->id, SILC_ID_CLIENT,
4116                                   cipher, hmac, passphrase);
4117
4118   /* Send command reply to sender */
4119   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4120                                                 SILC_STATUS_OK, ident, 2,
4121                                                 2, tmp_id, tmp_len2,
4122                                                 3, tmp_mask, 4);
4123   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4124                           packet->data, packet->len, FALSE);
4125     
4126   silc_buffer_free(packet);
4127   silc_free(channel_id);
4128   silc_buffer_free(cidp);
4129
4130  out:
4131   silc_server_command_free(cmd);
4132 }
4133
4134 /* Server side of CUMODE command. Changes client's mode on a channel. */
4135
4136 SILC_SERVER_CMD_FUNC(cumode)
4137 {
4138   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4139   SilcServer server = cmd->server;
4140   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4141   SilcIDListData idata = (SilcIDListData)client;
4142   SilcChannelID *channel_id;
4143   SilcClientID *client_id;
4144   SilcChannelEntry channel;
4145   SilcClientEntry target_client;
4146   SilcChannelClientEntry chl;
4147   SilcBuffer packet, idp;
4148   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4149   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4150   int notify = FALSE;
4151   uint16 ident = silc_command_get_ident(cmd->payload);
4152
4153   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4154
4155   /* Get Channel ID */
4156   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4157   if (!tmp_ch_id) {
4158     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4159                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4160     goto out;
4161   }
4162   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4163   if (!channel_id) {
4164     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4165                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4166     goto out;
4167   }
4168
4169   /* Get channel entry */
4170   channel = silc_idlist_find_channel_by_id(server->local_list, 
4171                                            channel_id, NULL);
4172   if (!channel) {
4173     channel = silc_idlist_find_channel_by_id(server->global_list, 
4174                                              channel_id, NULL);
4175     if (!channel) {
4176       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4177                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4178       goto out;
4179     }
4180   }
4181
4182   /* Check whether sender is on the channel */
4183   if (!silc_server_client_on_channel(client, channel)) {
4184     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4186     goto out;
4187   }
4188
4189   /* Check that client has rights to change other's rights */
4190   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4191   sender_mask = chl->mode;
4192   
4193   /* Get the target client's channel mode mask */
4194   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4195   if (!tmp_mask) {
4196     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4198     goto out;
4199   }
4200   SILC_GET32_MSB(target_mask, tmp_mask);
4201
4202   /* Get target Client ID */
4203   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4204   if (!tmp_id) {
4205     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4207     goto out;
4208   }
4209   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4210   if (!client_id) {
4211     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4213     goto out;
4214   }
4215
4216   /* Get target client's entry */
4217   target_client = silc_idlist_find_client_by_id(server->local_list, 
4218                                                 client_id, TRUE, NULL);
4219   if (!target_client) {
4220     target_client = silc_idlist_find_client_by_id(server->global_list, 
4221                                                   client_id, TRUE, NULL);
4222   }
4223
4224   if (target_client != client &&
4225       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4226       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4227     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4229     goto out;
4230   }
4231
4232   /* Check whether target client is on the channel */
4233   if (target_client != client) {
4234     if (!silc_server_client_on_channel(target_client, channel)) {
4235       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4237       goto out;
4238     }
4239
4240     /* Get entry to the channel user list */
4241     silc_hash_table_find(channel->user_list, target_client, NULL, 
4242                          (void *)&chl);
4243   }
4244
4245   /* 
4246    * Change the mode 
4247    */
4248
4249   /* If the target client is founder, no one else can change their mode
4250      but themselves. */
4251   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253                                           SILC_STATUS_ERR_NOT_YOU);
4254     goto out;
4255   }
4256
4257   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4258     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4259       /* The client tries to claim the founder rights. */
4260       unsigned char *tmp_auth;
4261       uint32 tmp_auth_len, auth_len;
4262       void *auth;
4263       
4264       if (target_client != client) {
4265         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266                                               SILC_STATUS_ERR_NOT_YOU);
4267         goto out;
4268       }
4269
4270       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4271           !channel->founder_key || !idata->public_key ||
4272           !silc_pkcs_public_key_compare(channel->founder_key, 
4273                                         idata->public_key)) {
4274         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4275                                               SILC_STATUS_ERR_NOT_YOU);
4276         goto out;
4277       }
4278
4279       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4280       if (!tmp_auth) {
4281         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4283         goto out;
4284       }
4285
4286       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4287               (void *)channel->founder_passwd : (void *)channel->founder_key);
4288       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4289                   channel->founder_passwd_len : 0);
4290       
4291       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4292                                  channel->founder_method, auth, auth_len,
4293                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4294         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295                                               SILC_STATUS_ERR_AUTH_FAILED);
4296         goto out;
4297       }
4298       
4299       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4300       notify = TRUE;
4301     }
4302   } else {
4303     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4304       if (target_client == client) {
4305         /* Remove channel founder rights from itself */
4306         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4307         notify = TRUE;
4308       } else {
4309         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310                                               SILC_STATUS_ERR_NOT_YOU);
4311         goto out;
4312       }
4313     }
4314   }
4315
4316   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4317     /* Promote to operator */
4318     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4319       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4320           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4321         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4323         goto out;
4324       }
4325
4326       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4327       notify = TRUE;
4328     }
4329   } else {
4330     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4331       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4332           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4333         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4334                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4335         goto out;
4336       }
4337
4338       /* Demote to normal user */
4339       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4340       notify = TRUE;
4341     }
4342   }
4343
4344   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4345   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4346
4347   /* Send notify to channel, notify only if mode was actually changed. */
4348   if (notify) {
4349     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4350                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4351                                        idp->data, idp->len,
4352                                        tmp_mask, 4, 
4353                                        tmp_id, tmp_len);
4354
4355     /* Set CUMODE notify type to network */
4356     if (!server->standalone)
4357       silc_server_send_notify_cumode(server, server->router->connection,
4358                                      server->server_type == SILC_ROUTER ? 
4359                                      TRUE : FALSE, channel,
4360                                      target_mask, client->id, 
4361                                      SILC_ID_CLIENT,
4362                                      target_client->id);
4363   }
4364
4365   /* Send command reply to sender */
4366   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4367                                                 SILC_STATUS_OK, ident, 3,
4368                                                 2, tmp_mask, 4,
4369                                                 3, tmp_ch_id, tmp_ch_len,
4370                                                 4, tmp_id, tmp_len);
4371   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4372                           packet->data, packet->len, FALSE);
4373     
4374   silc_buffer_free(packet);
4375   silc_free(channel_id);
4376   silc_free(client_id);
4377   silc_buffer_free(idp);
4378
4379  out:
4380   silc_server_command_free(cmd);
4381 }
4382
4383 /* Server side of KICK command. Kicks client out of channel. */
4384
4385 SILC_SERVER_CMD_FUNC(kick)
4386 {
4387   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4388   SilcServer server = cmd->server;
4389   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4390   SilcClientEntry target_client;
4391   SilcChannelID *channel_id;
4392   SilcClientID *client_id;
4393   SilcChannelEntry channel;
4394   SilcChannelClientEntry chl;
4395   SilcBuffer idp;
4396   uint32 tmp_len, target_idp_len;
4397   unsigned char *tmp, *comment, *target_idp;
4398
4399   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4400
4401   /* Get Channel ID */
4402   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4403   if (!tmp) {
4404     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4405                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4406     goto out;
4407   }
4408   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4409   if (!channel_id) {
4410     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4411                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4412     goto out;
4413   }
4414
4415   /* Get channel entry */
4416   channel = silc_idlist_find_channel_by_id(server->local_list, 
4417                                            channel_id, NULL);
4418   if (!channel) {
4419     channel = silc_idlist_find_channel_by_id(server->local_list, 
4420                                              channel_id, NULL);
4421     if (!channel) {
4422       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4423                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4424       goto out;
4425     }
4426   }
4427
4428   /* Check whether sender is on the channel */
4429   if (!silc_server_client_on_channel(client, channel)) {
4430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4431                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4432     goto out;
4433   }
4434
4435   /* Check that the kicker is channel operator or channel founder */
4436   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4437   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4438     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4439                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4440     goto out;
4441   }
4442   
4443   /* Get target Client ID */
4444   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4445   if (!target_idp) {
4446     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4447                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4448     goto out;
4449   }
4450   client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4451   if (!client_id) {
4452     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4453                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4454     goto out;
4455   }
4456
4457   /* Get target client's entry */
4458   target_client = silc_idlist_find_client_by_id(server->local_list, 
4459                                                 client_id, TRUE, NULL);
4460   if (!target_client) {
4461     target_client = silc_idlist_find_client_by_id(server->global_list, 
4462                                                   client_id, TRUE, NULL);
4463   }
4464
4465   /* Check that the target client is not channel founder. Channel founder
4466      cannot be kicked from the channel. */
4467   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4468   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4469     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4470                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4471     goto out;
4472   }
4473   
4474   /* Check whether target client is on the channel */
4475   if (!silc_server_client_on_channel(target_client, channel)) {
4476     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4477                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4478     goto out;
4479   }
4480
4481   /* Get comment */
4482   tmp_len = 0;
4483   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4484   if (tmp_len > 128)
4485     comment = NULL;
4486
4487   /* Send command reply to sender */
4488   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4489                                         SILC_STATUS_OK);
4490
4491   /* Send KICKED notify to local clients on the channel */
4492   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4493   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4494                                      SILC_NOTIFY_TYPE_KICKED, 3,
4495                                      target_idp, target_idp_len,
4496                                      comment, comment ? strlen(comment) : 0,
4497                                      idp->data, idp->len);
4498   silc_buffer_free(idp);
4499
4500   /* Remove the client from the channel. If the channel does not exist
4501      after removing the client then the client kicked itself off the channel
4502      and we don't have to send anything after that. */
4503   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4504                                            target_client, FALSE))
4505     goto out;
4506
4507   /* Send KICKED notify to primary route */
4508   if (!server->standalone)
4509     silc_server_send_notify_kicked(server, server->router->connection,
4510                                    server->server_type == SILC_ROUTER ?
4511                                    TRUE : FALSE, channel,
4512                                    target_client->id, comment);
4513
4514   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4515     /* Re-generate channel key */
4516     if (!silc_server_create_channel_key(server, channel, 0))
4517       goto out;
4518     
4519     /* Send the channel key to the channel. The key of course is not sent
4520        to the client who was kicked off the channel. */
4521     silc_server_send_channel_key(server, target_client->connection, channel, 
4522                                  server->server_type == SILC_ROUTER ? 
4523                                  FALSE : !server->standalone);
4524   }
4525
4526  out:
4527   silc_server_command_free(cmd);
4528 }
4529
4530 /* Server side of OPER command. Client uses this comand to obtain server
4531    operator privileges to this server/router. */
4532
4533 SILC_SERVER_CMD_FUNC(oper)
4534 {
4535   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4536   SilcServer server = cmd->server;
4537   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4538   unsigned char *username, *auth;
4539   uint32 tmp_len;
4540   SilcServerConfigSectionAdminConnection *admin;
4541   SilcIDListData idata = (SilcIDListData)client;
4542
4543   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4544
4545   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4546     goto out;
4547
4548   /* Get the username */
4549   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4550   if (!username) {
4551     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4552                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4553     goto out;
4554   }
4555
4556   /* Get the admin configuration */
4557   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4558                                         username, client->nickname);
4559   if (!admin) {
4560     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4561                                           username, client->nickname);
4562     if (!admin) {
4563       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4564                                             SILC_STATUS_ERR_AUTH_FAILED);
4565       goto out;
4566     }
4567   }
4568
4569   /* Get the authentication payload */
4570   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4571   if (!auth) {
4572     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4573                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4574     goto out;
4575   }
4576
4577   /* Verify the authentication data */
4578   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4579                              admin->auth_data, admin->auth_data_len,
4580                              idata->hash, client->id, SILC_ID_CLIENT)) {
4581     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4582                                           SILC_STATUS_ERR_AUTH_FAILED);
4583     goto out;
4584   }
4585
4586   /* Client is now server operator */
4587   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4588
4589   /* Send UMODE change to primary router */
4590   if (!server->standalone)
4591     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4592                                   client->id, client->mode);
4593
4594   /* Send reply to the sender */
4595   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4596                                         SILC_STATUS_OK);
4597
4598  out:
4599   silc_server_command_free(cmd);
4600 }
4601
4602 /* Server side of SILCOPER command. Client uses this comand to obtain router
4603    operator privileges to this router. */
4604
4605 SILC_SERVER_CMD_FUNC(silcoper)
4606 {
4607   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4608   SilcServer server = cmd->server;
4609   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4610   unsigned char *username, *auth;
4611   uint32 tmp_len;
4612   SilcServerConfigSectionAdminConnection *admin;
4613   SilcIDListData idata = (SilcIDListData)client;
4614
4615   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4616
4617   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4618     goto out;
4619
4620   if (server->server_type != SILC_ROUTER) {
4621     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4622                                           SILC_STATUS_ERR_AUTH_FAILED);
4623     goto out;
4624   }
4625
4626   /* Get the username */
4627   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4628   if (!username) {
4629     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4630                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4631     goto out;
4632   }
4633
4634   /* Get the admin configuration */
4635   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4636                                         username, client->nickname);
4637   if (!admin) {
4638     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4639                                           username, client->nickname);
4640     if (!admin) {
4641       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4642                                             SILC_STATUS_ERR_AUTH_FAILED);
4643       goto out;
4644     }
4645   }
4646
4647   /* Get the authentication payload */
4648   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4649   if (!auth) {
4650     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4651                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4652     goto out;
4653   }
4654
4655   /* Verify the authentication data */
4656   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4657                              admin->auth_data, admin->auth_data_len,
4658                              idata->hash, client->id, SILC_ID_CLIENT)) {
4659     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4660                                           SILC_STATUS_ERR_AUTH_FAILED);
4661     goto out;
4662   }
4663
4664   /* Client is now router operator */
4665   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4666
4667   /* Send UMODE change to primary router */
4668   if (!server->standalone)
4669     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4670                                   client->id, client->mode);
4671
4672   /* Send reply to the sender */
4673   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674                                         SILC_STATUS_OK);
4675
4676  out:
4677   silc_server_command_free(cmd);
4678 }
4679
4680 /* Server side command of CONNECT. Connects us to the specified remote
4681    server or router. */
4682
4683 SILC_SERVER_CMD_FUNC(connect)
4684 {
4685   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4686   SilcServer server = cmd->server;
4687   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4688   unsigned char *tmp, *host;
4689   uint32 tmp_len;
4690   uint32 port = SILC_PORT;
4691
4692   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4693
4694   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4695     goto out;
4696
4697   /* Check whether client has the permissions. */
4698   if (client->mode == SILC_UMODE_NONE) {
4699     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4700                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4701     goto out;
4702   }
4703
4704   if (server->server_type == SILC_ROUTER && 
4705       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4706     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4707                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4708     goto out;
4709   }
4710
4711   /* Get the remote server */
4712   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4713   if (!host) {
4714     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4715                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4716     goto out;
4717   }
4718
4719   /* Get port */
4720   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4721   if (tmp)
4722     SILC_GET32_MSB(port, tmp);
4723
4724   /* Create the connection. It is done with timeout and is async. */
4725   silc_server_create_connection(server, host, port);
4726
4727   /* Send reply to the sender */
4728   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4729                                         SILC_STATUS_OK);
4730
4731  out:
4732   silc_server_command_free(cmd);
4733 }
4734
4735 /* Server side of command BAN. This is used to manage the ban list of the
4736    channel. To add clients and remove clients from the ban list. */
4737
4738 SILC_SERVER_CMD_FUNC(ban)
4739 {
4740   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4741   SilcServer server = cmd->server;
4742   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4743   SilcBuffer packet;
4744   SilcChannelEntry channel;
4745   SilcChannelClientEntry chl;
4746   SilcChannelID *channel_id = NULL;
4747   unsigned char *id, *add, *del;
4748   uint32 id_len, tmp_len;
4749   uint16 ident = silc_command_get_ident(cmd->payload);
4750
4751   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4752     goto out;
4753
4754   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4755
4756   /* Get Channel ID */
4757   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4758   if (id) {
4759     channel_id = silc_id_payload_parse_id(id, id_len);
4760     if (!channel_id) {
4761       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4762                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4763       goto out;
4764     }
4765   }
4766
4767   /* Get channel entry. The server must know about the channel since the
4768      client is expected to be on the channel. */
4769   channel = silc_idlist_find_channel_by_id(server->local_list, 
4770                                            channel_id, NULL);
4771   if (!channel) {
4772     channel = silc_idlist_find_channel_by_id(server->global_list, 
4773                                              channel_id, NULL);
4774     if (!channel) {
4775       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4776                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4777       goto out;
4778     }
4779   }
4780
4781   /* Check whether this client is on the channel */
4782   if (!silc_server_client_on_channel(client, channel)) {
4783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4784                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4785     goto out;
4786   }
4787
4788   /* Get entry to the channel user list */
4789   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4790
4791   /* The client must be at least channel operator. */
4792   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4793     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4794                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4795     goto out;
4796   }
4797
4798   /* Get the new ban and add it to the ban list */
4799   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4800   if (add) {
4801     if (!channel->ban_list)
4802       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4803     else
4804       channel->ban_list = silc_realloc(channel->ban_list, 
4805                                        sizeof(*channel->ban_list) * 
4806                                        (tmp_len + 
4807                                         strlen(channel->ban_list) + 2));
4808     if (add[tmp_len - 1] == ',')
4809       add[tmp_len - 1] = '\0';
4810
4811     strncat(channel->ban_list, add, tmp_len);
4812     strncat(channel->ban_list, ",", 1);
4813   }
4814
4815   /* Get the ban to be removed and remove it from the list */
4816   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4817   if (del && channel->ban_list) {
4818     char *start, *end, *n;
4819
4820     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4821       silc_free(channel->ban_list);
4822       channel->ban_list = NULL;
4823     } else {
4824       start = strstr(channel->ban_list, del);
4825       if (start && strlen(start) >= tmp_len) {
4826         end = start + tmp_len;
4827         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4828         strncat(n, channel->ban_list, start - channel->ban_list);
4829         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4830                              end) - 1);
4831         silc_free(channel->ban_list);
4832         channel->ban_list = n;
4833       }
4834     }
4835   }
4836
4837   /* Send the BAN notify type to our primary router. */
4838   if (!server->standalone && (add || del))
4839     silc_server_send_notify_ban(server, server->router->connection,
4840                                 server->server_type == SILC_ROUTER ?
4841                                 TRUE : FALSE, channel, add, del);
4842
4843   /* Send the reply back to the client */
4844   packet = 
4845     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4846                                          SILC_STATUS_OK, ident, 2,
4847                                          2, id, id_len,
4848                                          3, channel->ban_list, 
4849                                          channel->ban_list ? 
4850                                          strlen(channel->ban_list) - 1 : 0);
4851   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4852                           packet->data, packet->len, FALSE);
4853     
4854   silc_buffer_free(packet);
4855
4856  out:
4857   silc_free(channel_id);
4858   silc_server_command_free(cmd);
4859 }
4860
4861 /* Server side command of CLOSE. Closes connection to a specified server. */
4862  
4863 SILC_SERVER_CMD_FUNC(close)
4864 {
4865   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4866   SilcServer server = cmd->server;
4867   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4868   SilcServerEntry server_entry;
4869   SilcSocketConnection sock;
4870   unsigned char *tmp;
4871   uint32 tmp_len;
4872   unsigned char *name;
4873   uint32 port = SILC_PORT;
4874
4875   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4876
4877   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4878     goto out;
4879
4880   /* Check whether client has the permissions. */
4881   if (client->mode == SILC_UMODE_NONE) {
4882     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4883                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4884     goto out;
4885   }
4886
4887   /* Get the remote server */
4888   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4889   if (!name) {
4890     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4891                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4892     goto out;
4893   }
4894
4895   /* Get port */
4896   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4897   if (tmp)
4898     SILC_GET32_MSB(port, tmp);
4899
4900   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4901                                                  name, port, FALSE, NULL);
4902   if (!server_entry)
4903     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4904                                                    name, port, FALSE, NULL);
4905   if (!server_entry) {
4906     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4907                                           SILC_STATUS_ERR_NO_SERVER_ID);
4908     goto out;
4909   }
4910
4911   /* Send reply to the sender */
4912   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4913                                         SILC_STATUS_OK);
4914
4915   /* Close the connection to the server */
4916   sock = (SilcSocketConnection)server_entry->connection;
4917
4918   /* If we shutdown primary router connection manually then don't trigger
4919      any reconnect or backup router connections, by setting the router
4920      to NULL here. */
4921   if (server->router == server_entry) {
4922     server->id_entry->router = NULL;
4923     server->router = NULL;
4924     server->standalone = TRUE;
4925   }
4926   silc_server_free_sock_user_data(server, sock, NULL);
4927   silc_server_close_connection(server, sock);
4928   
4929  out:
4930   silc_server_command_free(cmd);
4931 }
4932
4933 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4934    active connections. */
4935  
4936 SILC_SERVER_CMD_FUNC(shutdown)
4937 {
4938   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4939   SilcServer server = cmd->server;
4940   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4941
4942   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4943
4944   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4945     goto out;
4946
4947   /* Check whether client has the permission. */
4948   if (client->mode == SILC_UMODE_NONE) {
4949     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4950                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4951     goto out;
4952   }
4953
4954   /* Send reply to the sender */
4955   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4956                                         SILC_STATUS_OK);
4957
4958   /* Then, gracefully, or not, bring the server down. */
4959   silc_server_stop(server);
4960   exit(0);
4961
4962  out:
4963   silc_server_command_free(cmd);
4964 }
4965  
4966 /* Server side command of LEAVE. Removes client from a channel. */
4967
4968 SILC_SERVER_CMD_FUNC(leave)
4969 {
4970   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4971   SilcServer server = cmd->server;
4972   SilcSocketConnection sock = cmd->sock;
4973   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4974   SilcChannelID *id = NULL;
4975   SilcChannelEntry channel;
4976   uint32 len;
4977   unsigned char *tmp;
4978
4979   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4980
4981   /* Get Channel ID */
4982   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4983   if (!tmp) {
4984     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4985                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4986     goto out;
4987   }
4988   id = silc_id_payload_parse_id(tmp, len);
4989   if (!id) {
4990     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4991                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4992     goto out;
4993   }
4994
4995   /* Get channel entry */
4996   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4997   if (!channel) {
4998     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4999     if (!channel) {
5000       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5001                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5002       goto out;
5003     }
5004   }
5005
5006   /* Check whether this client is on the channel */
5007   if (!silc_server_client_on_channel(id_entry, channel)) {
5008     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5009                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
5010     goto out;
5011   }
5012
5013   /* Notify routers that they should remove this client from their list
5014      of clients on the channel. Send LEAVE notify type. */
5015   if (!server->standalone)
5016     silc_server_send_notify_leave(server, server->router->connection,
5017                                   server->server_type == SILC_ROUTER ?
5018                                   TRUE : FALSE, channel, id_entry->id);
5019
5020   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5021                                         SILC_STATUS_OK);
5022
5023   /* Remove client from channel */
5024   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5025                                            TRUE))
5026     /* If the channel does not exist anymore we won't send anything */
5027     goto out;
5028
5029   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5030     /* Re-generate channel key */
5031     if (!silc_server_create_channel_key(server, channel, 0))
5032       goto out;
5033
5034     /* Send the channel key */
5035     silc_server_send_channel_key(server, NULL, channel, 
5036                                  server->server_type == SILC_ROUTER ? 
5037                                  FALSE : !server->standalone);
5038   }
5039
5040  out:
5041   silc_free(id);
5042   silc_server_command_free(cmd);
5043 }
5044
5045 /* Server side of command USERS. Resolves clients and their USERS currently
5046    joined on the requested channel. The list of Client ID's and their modes
5047    on the channel is sent back. */
5048
5049 SILC_SERVER_CMD_FUNC(users)
5050 {
5051   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5052   SilcServer server = cmd->server;
5053   SilcChannelEntry channel;
5054   SilcChannelID *id = NULL;
5055   SilcBuffer packet, idp;
5056   unsigned char *channel_id;
5057   uint32 channel_id_len;
5058   SilcBuffer client_id_list;
5059   SilcBuffer client_mode_list;
5060   unsigned char lc[4];
5061   uint32 list_count = 0;
5062   uint16 ident = silc_command_get_ident(cmd->payload);
5063   char *channel_name;
5064
5065   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5066
5067   /* Get Channel ID */
5068   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5069
5070   /* Get channel name */
5071   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5072
5073   if (!channel_id && !channel_name) {
5074     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5075                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5076     goto out;
5077   }
5078
5079   if (channel_id) {
5080     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5081     if (!id) {
5082       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5083                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5084       goto out;
5085     }
5086   }
5087
5088   /* If we are server and we don't know about this channel we will send
5089      the command to our router. If we know about the channel then we also
5090      have the list of users already. */
5091   if (id)
5092     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5093   else
5094     channel = silc_idlist_find_channel_by_name(server->local_list, 
5095                                                channel_name, NULL);
5096
5097   if (!channel || channel->disabled) {
5098     if (server->server_type != SILC_ROUTER && !server->standalone &&
5099         !cmd->pending) {
5100       SilcBuffer tmpbuf;
5101       
5102       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5103       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5104       
5105       /* Send USERS command */
5106       silc_server_packet_send(server, server->router->connection,
5107                               SILC_PACKET_COMMAND, cmd->packet->flags,
5108                               tmpbuf->data, tmpbuf->len, TRUE);
5109       
5110       /* Reprocess this packet after received reply */
5111       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5112                                   silc_command_get_ident(cmd->payload),
5113                                   silc_server_command_users,
5114                                   silc_server_command_dup(cmd));
5115       cmd->pending = TRUE;
5116       silc_command_set_ident(cmd->payload, ident);
5117       silc_buffer_free(tmpbuf);
5118       silc_free(id);
5119       goto out;
5120     }
5121
5122     /* Check the global list as well. */
5123     if (id)
5124       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5125     else
5126       channel = silc_idlist_find_channel_by_name(server->global_list, 
5127                                                  channel_name, NULL);
5128     if (!channel) {
5129       /* Channel really does not exist */
5130       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5131                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5132       goto out;
5133     }
5134   }
5135
5136   /* If the channel is private or secret do not send anything, unless the
5137      user requesting this command is on the channel. */
5138   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5139     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5140         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5141       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5142                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5143       goto out;
5144     }
5145   } else {
5146     if (channel->mode & 
5147         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5148       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5149                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5150       goto out;
5151     }
5152   }
5153
5154   /* Get the users list */
5155   silc_server_get_users_on_channel(server, channel, &client_id_list,
5156                                    &client_mode_list, &list_count);
5157
5158   /* List count */
5159   SILC_PUT32_MSB(list_count, lc);
5160
5161   /* Send reply */
5162   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5163   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5164                                                 SILC_STATUS_OK, ident, 4,
5165                                                 2, idp->data, idp->len,
5166                                                 3, lc, 4,
5167                                                 4, client_id_list->data,
5168                                                 client_id_list->len,
5169                                                 5, client_mode_list->data,
5170                                                 client_mode_list->len);
5171   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5172                           packet->data, packet->len, FALSE);
5173     
5174   silc_buffer_free(idp);
5175   silc_buffer_free(packet);
5176   silc_buffer_free(client_id_list);
5177   silc_buffer_free(client_mode_list);
5178   silc_free(id);
5179
5180  out:
5181   silc_server_command_free(cmd);
5182 }
5183
5184 /* Server side of command GETKEY. This fetches the client's public key
5185    from the server where to the client is connected. */
5186
5187 SILC_SERVER_CMD_FUNC(getkey)
5188 {
5189   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5190   SilcServer server = cmd->server;
5191   SilcBuffer packet;
5192   SilcClientEntry client;
5193   SilcServerEntry server_entry;
5194   SilcClientID *client_id = NULL;
5195   SilcServerID *server_id = NULL;
5196   SilcIDPayload idp = NULL;
5197   uint16 ident = silc_command_get_ident(cmd->payload);
5198   unsigned char *tmp, *pkdata;
5199   uint32 tmp_len, pklen;
5200   SilcBuffer pk = NULL;
5201   SilcIdType id_type;
5202
5203   SILC_LOG_DEBUG(("Start"));
5204
5205   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5206   if (!tmp) {
5207     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5208                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5209     goto out;
5210   }
5211   idp = silc_id_payload_parse(tmp, tmp_len);
5212   if (!idp) {
5213     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5214                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5215     goto out;
5216   }
5217
5218   id_type = silc_id_payload_get_type(idp);
5219   if (id_type == SILC_ID_CLIENT) {
5220     client_id = silc_id_payload_get_id(idp);
5221
5222     /* If the client is not found from local list there is no chance it
5223        would be locally connected client so send the command further. */
5224     client = silc_idlist_find_client_by_id(server->local_list, 
5225                                            client_id, TRUE, NULL);
5226     if (!client)
5227       client = silc_idlist_find_client_by_id(server->global_list, 
5228                                              client_id, TRUE, NULL);
5229     
5230     if ((!client && !cmd->pending && !server->standalone) ||
5231         (client && !client->connection && !cmd->pending) ||
5232         (client && !client->data.public_key && !cmd->pending)) {
5233       SilcBuffer tmpbuf;
5234       uint16 old_ident;
5235       SilcSocketConnection dest_sock;
5236       
5237       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5238                                                client_id, NULL);
5239       if (!dest_sock)
5240         goto out;
5241       
5242       old_ident = silc_command_get_ident(cmd->payload);
5243       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5244       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5245       
5246       silc_server_packet_send(server, dest_sock,
5247                               SILC_PACKET_COMMAND, cmd->packet->flags,
5248                               tmpbuf->data, tmpbuf->len, TRUE);
5249       
5250       /* Reprocess this packet after received reply from router */
5251       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5252                                   silc_command_get_ident(cmd->payload),
5253                                   silc_server_command_getkey,
5254                                   silc_server_command_dup(cmd));
5255       cmd->pending = TRUE;
5256       silc_command_set_ident(cmd->payload, old_ident);
5257       silc_buffer_free(tmpbuf);
5258       goto out;
5259     }
5260
5261     if (!client) {
5262       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5263                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5264       goto out;
5265     }
5266
5267     /* The client is locally connected, just get the public key and
5268        send it back. If they key does not exist then do not send it, 
5269        send just OK reply */
5270     if (!client->data.public_key) {
5271       pkdata = NULL;
5272       pklen = 0;
5273     } else {
5274       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5275       pk = silc_buffer_alloc(4 + tmp_len);
5276       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5277       silc_buffer_format(pk,
5278                          SILC_STR_UI_SHORT(tmp_len),
5279                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5280                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5281                          SILC_STR_END);
5282       silc_free(tmp);
5283       pkdata = pk->data;
5284       pklen = pk->len;
5285     }
5286   } else if (id_type == SILC_ID_SERVER) {
5287     server_id = silc_id_payload_get_id(idp);
5288
5289     /* If the server is not found from local list there is no chance it
5290        would be locally connected server so send the command further. */
5291     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5292                                                  server_id, TRUE, NULL);
5293     if (!server_entry)
5294       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5295                                                    server_id, TRUE, NULL);
5296     
5297     if (server_entry != server->id_entry &&
5298         ((!server_entry && !cmd->pending && !server->standalone) ||
5299          (server_entry && !server_entry->connection && !cmd->pending &&
5300           !server->standalone) ||
5301          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5302           !server->standalone))) {
5303       SilcBuffer tmpbuf;
5304       uint16 old_ident;
5305       
5306       old_ident = silc_command_get_ident(cmd->payload);
5307       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5308       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5309       
5310       silc_server_packet_send(server, server->router->connection,
5311                               SILC_PACKET_COMMAND, cmd->packet->flags,
5312                               tmpbuf->data, tmpbuf->len, TRUE);
5313       
5314       /* Reprocess this packet after received reply from router */
5315       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5316                                   silc_command_get_ident(cmd->payload),
5317                                   silc_server_command_getkey,
5318                                   silc_server_command_dup(cmd));
5319       cmd->pending = TRUE;
5320       
5321       silc_command_set_ident(cmd->payload, old_ident);
5322       silc_buffer_free(tmpbuf);
5323       goto out;
5324     }
5325
5326     if (!server_entry) {
5327       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5328                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5329       goto out;
5330     }
5331
5332     /* If they key does not exist then do not send it, send just OK reply */
5333     if (!server_entry->data.public_key) {
5334       pkdata = NULL;
5335       pklen = 0;
5336     } else {
5337       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5338                                         &tmp_len);
5339       pk = silc_buffer_alloc(4 + tmp_len);
5340       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5341       silc_buffer_format(pk,
5342                          SILC_STR_UI_SHORT(tmp_len),
5343                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5344                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5345                          SILC_STR_END);
5346       silc_free(tmp);
5347       pkdata = pk->data;
5348       pklen = pk->len;
5349     }
5350   } else {
5351     goto out;
5352   }
5353
5354   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5355   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5356                                                 SILC_STATUS_OK, ident, 
5357                                                 pkdata ? 2 : 1,
5358                                                 2, tmp, tmp_len,
5359                                                 3, pkdata, pklen);
5360   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5361                           packet->data, packet->len, FALSE);
5362   silc_buffer_free(packet);
5363
5364   if (pk)
5365     silc_buffer_free(pk);
5366
5367  out:
5368   if (idp)
5369     silc_id_payload_free(idp);
5370   silc_free(client_id);
5371   silc_free(server_id);
5372   silc_server_command_free(cmd);
5373 }