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