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 (silc_string_match(channel->ban_list, check) ||
3096           silc_string_match(channel->ban_list, check2)) {
3097         silc_server_command_send_status_reply(
3098                                       cmd, SILC_COMMAND_JOIN,
3099                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3100         goto out;
3101       }
3102     }
3103     
3104     /* Check user count limit if set. */
3105     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3106       if (silc_hash_table_count(channel->user_list) + 1 > 
3107           channel->user_limit) {
3108         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3109                                               SILC_STATUS_ERR_CHANNEL_IS_FULL);
3110         goto out;
3111       }
3112     }
3113   }
3114
3115   /* Check the channel passphrase if set. */
3116   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3117     /* Get passphrase */
3118     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3119     if (tmp) {
3120       passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3121       memcpy(passphrase, tmp, tmp_len);
3122     }
3123   
3124     if (!passphrase || !channel->passphrase ||
3125         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3126       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3127                                             SILC_STATUS_ERR_BAD_PASSWORD);
3128       goto out;
3129     }
3130   }
3131
3132   /*
3133    * Client is allowed to join to the channel. Make it happen.
3134    */
3135
3136   /* Check whether the client already is on the channel */
3137   if (silc_server_client_on_channel(client, channel)) {
3138     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3139                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3140     goto out;
3141   }
3142
3143   /* Generate new channel key as protocol dictates */
3144   if (create_key) {
3145     if (!silc_server_create_channel_key(server, channel, 0))
3146       goto out;
3147
3148     /* Send the channel key. This is broadcasted to the channel but is not
3149        sent to the client who is joining to the channel. */
3150     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3151       silc_server_send_channel_key(server, NULL, channel, 
3152                                    server->server_type == SILC_ROUTER ? 
3153                                    FALSE : !server->standalone);
3154   }
3155
3156   /* Join the client to the channel by adding it to channel's user list.
3157      Add also the channel to client entry's channels list for fast cross-
3158      referencing. */
3159   chl = silc_calloc(1, sizeof(*chl));
3160   chl->mode = umode;
3161   chl->client = client;
3162   chl->channel = channel;
3163   silc_hash_table_add(channel->user_list, client, chl);
3164   silc_hash_table_add(client->channels, channel, chl);
3165
3166   /* Get users on the channel */
3167   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3168                                    &user_count);
3169
3170   /* Encode Client ID Payload of the original client who wants to join */
3171   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3172
3173   /* Encode command reply packet */
3174   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3175   SILC_PUT32_MSB(channel->mode, mode);
3176   SILC_PUT32_MSB(created, tmp2);
3177   SILC_PUT32_MSB(user_count, tmp3);
3178
3179   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3180     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3181     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3182                                            strlen(channel->channel_key->
3183                                                   cipher->name),
3184                                            channel->channel_key->cipher->name,
3185                                            channel->key_len / 8, channel->key);
3186     silc_free(tmp);
3187   }
3188
3189   reply = 
3190     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3191                                          SILC_STATUS_OK, ident, 13,
3192                                          2, channel->channel_name,
3193                                          strlen(channel->channel_name),
3194                                          3, chidp->data, chidp->len,
3195                                          4, clidp->data, clidp->len,
3196                                          5, mode, 4,
3197                                          6, tmp2, 4,
3198                                          7, keyp ? keyp->data : NULL, 
3199                                          keyp ? keyp->len : 0,
3200                                          8, channel->ban_list, 
3201                                          channel->ban_list ?
3202                                          strlen(channel->ban_list) : 0,
3203                                          9, channel->invite_list,
3204                                          channel->invite_list ?
3205                                          strlen(channel->invite_list) : 0,
3206                                          10, channel->topic,
3207                                          channel->topic ?
3208                                          strlen(channel->topic) : 0,
3209                                          11, silc_hmac_get_name(channel->hmac),
3210                                          strlen(silc_hmac_get_name(channel->
3211                                                                    hmac)),
3212                                          12, tmp3, 4,
3213                                          13, user_list->data, user_list->len,
3214                                          14, mode_list->data, 
3215                                          mode_list->len);
3216
3217   /* Send command reply */
3218   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3219                           reply->data, reply->len, FALSE);
3220
3221   /* Send JOIN notify to locally connected clients on the channel. If
3222      we are normal server then router will send or have sent JOIN notify
3223      already. However since we've added the client already to our channel
3224      we'll ignore it (in packet_receive.c) so we must send it here. If
3225      we are router then this will send it to local clients and local
3226      servers. */
3227   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3228                                      SILC_NOTIFY_TYPE_JOIN, 2,
3229                                      clidp->data, clidp->len,
3230                                      chidp->data, chidp->len);
3231
3232   if (!cmd->pending) {
3233     /* Send JOIN notify packet to our primary router */
3234     if (!server->standalone)
3235       silc_server_send_notify_join(server, server->router->connection,
3236                                    server->server_type == SILC_ROUTER ?
3237                                    TRUE : FALSE, channel, client->id);
3238
3239     if (keyp)
3240       /* Distribute the channel key to all backup routers. */
3241       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3242                               keyp->data, keyp->len, FALSE, TRUE);
3243
3244     /* If client became founder by providing correct founder auth data
3245        notify the mode change to the channel. */
3246     if (founder) {
3247       SILC_PUT32_MSB(chl->mode, mode);
3248       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3249                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3250                                          clidp->data, clidp->len,
3251                                          mode, 4, clidp->data, clidp->len);
3252       
3253       /* Set CUMODE notify type to network */
3254       if (!server->standalone)
3255         silc_server_send_notify_cumode(server, server->router->connection,
3256                                        server->server_type == SILC_ROUTER ? 
3257                                        TRUE : FALSE, channel,
3258                                        chl->mode, client->id, SILC_ID_CLIENT,
3259                                        client->id);
3260     }
3261   }
3262
3263   silc_buffer_free(reply);
3264   silc_buffer_free(clidp);
3265   silc_buffer_free(chidp);
3266   silc_buffer_free(keyp);
3267   silc_buffer_free(user_list);
3268   silc_buffer_free(mode_list);
3269
3270  out:
3271   silc_free(passphrase);
3272 }
3273
3274 /* Server side of command JOIN. Joins client into requested channel. If 
3275    the channel does not exist it will be created. */
3276
3277 SILC_SERVER_CMD_FUNC(join)
3278 {
3279   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3280   SilcServer server = cmd->server;
3281   unsigned char *auth;
3282   uint32 tmp_len, auth_len;
3283   char *tmp, *channel_name = NULL, *cipher, *hmac;
3284   SilcChannelEntry channel;
3285   uint32 umode = 0;
3286   bool created = FALSE, create_key = TRUE;
3287   SilcClientID *client_id;
3288
3289   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3290
3291   /* Get channel name */
3292   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3293   if (!tmp) {
3294     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3295                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3296     goto out;
3297   }
3298   channel_name = tmp;
3299
3300   if (strlen(channel_name) > 256)
3301     channel_name[255] = '\0';
3302
3303   if (silc_server_command_bad_chars(channel_name) == TRUE) {
3304     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3305                                           SILC_STATUS_ERR_BAD_CHANNEL);
3306     goto out;
3307   }
3308
3309   /* Get Client ID of the client who is joining to the channel */
3310   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3311   if (!tmp) {
3312     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3313                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3314     goto out;
3315   }
3316   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3317   if (!client_id) {
3318     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3319                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3320     goto out;
3321   }
3322
3323   /* Get cipher, hmac name and auth payload */
3324   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3325   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3326   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3327
3328   /* See if the channel exists */
3329   channel = silc_idlist_find_channel_by_name(server->local_list, 
3330                                              channel_name, NULL);
3331
3332   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3333     /* If this is coming from client the Client ID in the command packet must
3334        be same as the client's ID. */
3335     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3336       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3337       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3338         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3339                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3340         goto out;
3341       }
3342     }
3343
3344     if (!channel || channel->disabled) {
3345       /* Channel not found */
3346
3347       /* If we are standalone server we don't have a router, we just create 
3348          the channel by ourselves. */
3349       if (server->standalone) {
3350         channel = silc_server_create_new_channel(server, server->id, cipher, 
3351                                                  hmac, channel_name, TRUE);
3352         if (!channel) {
3353           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3354                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3355           goto out;
3356         }
3357         
3358         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3359         created = TRUE;
3360         create_key = FALSE;
3361         
3362       } else {
3363
3364         /* The channel does not exist on our server. If we are normal server 
3365            we will send JOIN command to our router which will handle the
3366            joining procedure (either creates the channel if it doesn't exist 
3367            or joins the client to it). */
3368         if (server->server_type != SILC_ROUTER) {
3369           SilcBuffer tmpbuf;
3370           uint16 old_ident;
3371
3372           /* If this is pending command callback then we've resolved
3373              it and it didn't work, return since we've notified the
3374              client already in the command reply callback. */
3375           if (cmd->pending)
3376             goto out;
3377           
3378           old_ident = silc_command_get_ident(cmd->payload);
3379           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3380           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3381           
3382           /* Send JOIN command to our router */
3383           silc_server_packet_send(server, (SilcSocketConnection)
3384                                   server->router->connection,
3385                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3386                                   tmpbuf->data, tmpbuf->len, TRUE);
3387           
3388           /* Reprocess this packet after received reply from router */
3389           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3390                                       silc_command_get_ident(cmd->payload),
3391                                       silc_server_command_join,
3392                                       silc_server_command_dup(cmd));
3393           cmd->pending = TRUE;
3394           goto out;
3395         }
3396         
3397         /* We are router and the channel does not seem exist so we will check
3398            our global list as well for the channel. */
3399         channel = silc_idlist_find_channel_by_name(server->global_list, 
3400                                                    channel_name, NULL);
3401         if (!channel) {
3402           /* Channel really does not exist, create it */
3403           channel = silc_server_create_new_channel(server, server->id, cipher, 
3404                                                    hmac, channel_name, TRUE);
3405           if (!channel) {
3406             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3407                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3408             goto out;
3409           }
3410
3411           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3412           created = TRUE;
3413           create_key = FALSE;
3414         }
3415       }
3416     }
3417   } else {
3418     if (!channel) {
3419       /* Channel not found */
3420
3421       /* If the command came from router and we are normal server then
3422          something went wrong with the joining as the channel was not found.
3423          We can't do anything else but ignore this. */
3424       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3425           server->server_type != SILC_ROUTER)
3426         goto out;
3427       
3428       /* We are router and the channel does not seem exist so we will check
3429          our global list as well for the channel. */
3430       channel = silc_idlist_find_channel_by_name(server->global_list, 
3431                                                  channel_name, NULL);
3432       if (!channel) {
3433         /* Channel really does not exist, create it */
3434         channel = silc_server_create_new_channel(server, server->id, cipher, 
3435                                                  hmac, channel_name, TRUE);
3436         if (!channel) {
3437           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3438                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3439           goto out;
3440         }
3441
3442         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3443         created = TRUE;
3444         create_key = FALSE;
3445       }
3446     }
3447   }
3448
3449   /* Check whether the channel was created by our router */
3450   if (cmd->pending && context2) {
3451     SilcServerCommandReplyContext reply = 
3452       (SilcServerCommandReplyContext)context2;
3453
3454     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3455       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3456       SILC_GET32_MSB(created, tmp);
3457       create_key = FALSE;       /* Router returned the key already */
3458     }
3459
3460     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3461       created = TRUE;
3462   }
3463
3464   /* If the channel does not have global users and is also empty the client
3465      will be the channel founder and operator. */
3466   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3467     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3468
3469   /* Join to the channel */
3470   silc_server_command_join_channel(server, cmd, channel, client_id,
3471                                    created, create_key, umode,
3472                                    auth, auth_len);
3473
3474   silc_free(client_id);
3475
3476  out:
3477   silc_server_command_free(cmd);
3478 }
3479
3480 /* Server side of command MOTD. Sends server's current "message of the
3481    day" to the client. */
3482
3483 SILC_SERVER_CMD_FUNC(motd)
3484 {
3485   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3486   SilcServer server = cmd->server;
3487   SilcBuffer packet, idp;
3488   char *motd, *dest_server;
3489   uint32 motd_len;
3490   uint16 ident = silc_command_get_ident(cmd->payload);
3491   
3492   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3493
3494   /* Get server name */
3495   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3496   if (!dest_server) {
3497     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3498                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3499     goto out;
3500   }
3501
3502   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3503     /* Send our MOTD */
3504
3505     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3506
3507     if (server->config && server->config->motd && 
3508         server->config->motd->motd_file) {
3509       /* Send motd */
3510       motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3511       if (!motd)
3512         goto out;
3513       
3514       motd[motd_len] = 0;
3515       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3516                                                     SILC_STATUS_OK, ident, 2,
3517                                                     2, idp, idp->len,
3518                                                     3, motd, motd_len);
3519     } else {
3520       /* No motd */
3521       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3522                                                     SILC_STATUS_OK, ident, 1,
3523                                                     2, idp, idp->len);
3524     }
3525
3526     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3527                             packet->data, packet->len, FALSE);
3528     silc_buffer_free(packet);
3529     silc_buffer_free(idp);
3530   } else {
3531     SilcServerEntry entry;
3532
3533     /* Check whether we have this server cached */
3534     entry = silc_idlist_find_server_by_name(server->global_list,
3535                                             dest_server, TRUE, NULL);
3536     if (!entry) {
3537       entry = silc_idlist_find_server_by_name(server->local_list,
3538                                               dest_server, TRUE, NULL);
3539     }
3540
3541     if (server->server_type != SILC_SERVER && !cmd->pending && 
3542         entry && !entry->motd) {
3543       /* Send to the server */
3544       SilcBuffer tmpbuf;
3545       uint16 old_ident;
3546
3547       old_ident = silc_command_get_ident(cmd->payload);
3548       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3549       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3550
3551       silc_server_packet_send(server, entry->connection,
3552                               SILC_PACKET_COMMAND, cmd->packet->flags,
3553                               tmpbuf->data, tmpbuf->len, TRUE);
3554
3555       /* Reprocess this packet after received reply from router */
3556       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3557                                   silc_command_get_ident(cmd->payload),
3558                                   silc_server_command_motd,
3559                                   silc_server_command_dup(cmd));
3560       cmd->pending = TRUE;
3561       silc_command_set_ident(cmd->payload, old_ident);
3562       silc_buffer_free(tmpbuf);
3563       goto out;
3564     }
3565
3566     if (!entry && !cmd->pending && !server->standalone) {
3567       /* Send to the primary router */
3568       SilcBuffer tmpbuf;
3569       uint16 old_ident;
3570
3571       old_ident = silc_command_get_ident(cmd->payload);
3572       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3573       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3574
3575       silc_server_packet_send(server, server->router->connection,
3576                               SILC_PACKET_COMMAND, cmd->packet->flags,
3577                               tmpbuf->data, tmpbuf->len, TRUE);
3578
3579       /* Reprocess this packet after received reply from router */
3580       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3581                                   silc_command_get_ident(cmd->payload),
3582                                   silc_server_command_motd,
3583                                   silc_server_command_dup(cmd));
3584       cmd->pending = TRUE;
3585       silc_command_set_ident(cmd->payload, old_ident);
3586       silc_buffer_free(tmpbuf);
3587       goto out;
3588     }
3589
3590     if (!entry) {
3591       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3592                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3593       goto out;
3594     }
3595
3596     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3597     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3598                                                   SILC_STATUS_OK, ident, 2,
3599                                                   2, idp, idp->len,
3600                                                   3, entry->motd,
3601                                                   entry->motd ? 
3602                                                   strlen(entry->motd) : 0);
3603     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3604                             packet->data, packet->len, FALSE);
3605     silc_buffer_free(packet);
3606     silc_buffer_free(idp);
3607   }
3608
3609  out:
3610   silc_server_command_free(cmd);
3611 }
3612
3613 /* Server side of command UMODE. Client can use this command to set/unset
3614    user mode. Client actually cannot set itself to be as server/router
3615    operator so this can be used only to unset the modes. */
3616
3617 SILC_SERVER_CMD_FUNC(umode)
3618 {
3619   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3620   SilcServer server = cmd->server;
3621   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3622   SilcBuffer packet;
3623   unsigned char *tmp_mask;
3624   uint32 mask;
3625   uint16 ident = silc_command_get_ident(cmd->payload);
3626
3627   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3628     goto out;
3629
3630   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3631
3632   /* Get the client's mode mask */
3633   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3634   if (!tmp_mask) {
3635     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3636                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3637     goto out;
3638   }
3639   SILC_GET32_MSB(mask, tmp_mask);
3640
3641   /* 
3642    * Change the mode 
3643    */
3644
3645   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3646     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3647       /* Cannot operator mode */
3648       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3649                                             SILC_STATUS_ERR_PERM_DENIED);
3650       goto out;
3651     }
3652   } else {
3653     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3654       /* Remove the server operator rights */
3655       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3656   }
3657
3658   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3659     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3660       /* Cannot operator mode */
3661       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3662                                             SILC_STATUS_ERR_PERM_DENIED);
3663       goto out;
3664     }
3665   } else {
3666     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3667       /* Remove the router operator rights */
3668       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3669   }
3670
3671   if (mask & SILC_UMODE_GONE) {
3672     client->mode |= SILC_UMODE_GONE;
3673   } else {
3674     if (client->mode & SILC_UMODE_GONE)
3675       /* Remove the gone status */
3676       client->mode &= ~SILC_UMODE_GONE;
3677   }
3678
3679   /* Send UMODE change to primary router */
3680   if (!server->standalone)
3681     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3682                                   client->id, client->mode);
3683
3684   /* Send command reply to sender */
3685   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3686                                                 SILC_STATUS_OK, ident, 1,
3687                                                 2, tmp_mask, 4);
3688   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3689                           packet->data, packet->len, FALSE);
3690   silc_buffer_free(packet);
3691
3692  out:
3693   silc_server_command_free(cmd);
3694 }
3695
3696 /* Checks that client has rights to add or remove channel modes. If any
3697    of the checks fails FALSE is returned. */
3698
3699 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3700                                    SilcChannelClientEntry client,
3701                                    uint32 mode)
3702 {
3703   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3704   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3705
3706   /* Check whether has rights to change anything */
3707   if (!is_op && !is_fo)
3708     return FALSE;
3709
3710   /* Check whether has rights to change everything */
3711   if (is_op && is_fo)
3712     return TRUE;
3713
3714   /* We know that client is channel operator, check that they are not
3715      changing anything that requires channel founder rights. Rest of the
3716      modes are available automatically for channel operator. */
3717
3718   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3719     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3720       if (is_op && !is_fo)
3721         return FALSE;
3722   } else {
3723     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3724       if (is_op && !is_fo)
3725         return FALSE;
3726     }
3727   }
3728   
3729   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3730     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3731       if (is_op && !is_fo)
3732         return FALSE;
3733   } else {
3734     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3735       if (is_op && !is_fo)
3736         return FALSE;
3737     }
3738   }
3739
3740   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3741     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3742       if (is_op && !is_fo)
3743         return FALSE;
3744   } else {
3745     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3746       if (is_op && !is_fo)
3747         return FALSE;
3748     }
3749   }
3750   
3751   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3752     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3753       if (is_op && !is_fo)
3754         return FALSE;
3755   } else {
3756     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3757       if (is_op && !is_fo)
3758         return FALSE;
3759     }
3760   }
3761   
3762   return TRUE;
3763 }
3764
3765 /* Server side command of CMODE. Changes channel mode */
3766
3767 SILC_SERVER_CMD_FUNC(cmode)
3768 {
3769   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3770   SilcServer server = cmd->server;
3771   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3772   SilcIDListData idata = (SilcIDListData)client;
3773   SilcChannelID *channel_id;
3774   SilcChannelEntry channel;
3775   SilcChannelClientEntry chl;
3776   SilcBuffer packet, cidp;
3777   unsigned char *tmp, *tmp_id, *tmp_mask;
3778   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3779   uint32 mode_mask, tmp_len, tmp_len2;
3780   uint16 ident = silc_command_get_ident(cmd->payload);
3781
3782   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3783
3784   /* Get Channel ID */
3785   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3786   if (!tmp_id) {
3787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3789     goto out;
3790   }
3791   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3792   if (!channel_id) {
3793     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3794                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3795     goto out;
3796   }
3797
3798   /* Get the channel mode mask */
3799   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3800   if (!tmp_mask) {
3801     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3802                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3803     goto out;
3804   }
3805   SILC_GET32_MSB(mode_mask, tmp_mask);
3806
3807   /* Get channel entry */
3808   channel = silc_idlist_find_channel_by_id(server->local_list, 
3809                                            channel_id, NULL);
3810   if (!channel) {
3811     channel = silc_idlist_find_channel_by_id(server->global_list, 
3812                                              channel_id, NULL);
3813     if (!channel) {
3814       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3815                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3816       goto out;
3817     }
3818   }
3819
3820   /* Check whether this client is on the channel */
3821   if (!silc_server_client_on_channel(client, channel)) {
3822     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3824     goto out;
3825   }
3826
3827   /* Get entry to the channel user list */
3828   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3829
3830   /* Check that client has rights to change any requested channel modes */
3831   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3832     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3833                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3834     goto out;
3835   }
3836
3837   /*
3838    * Check the modes. Modes that requires nothing special operation are
3839    * not checked here.
3840    */
3841
3842   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3843     /* Channel uses private keys to protect traffic. Client(s) has set the
3844        key locally they want to use, server does not know that key. */
3845     /* Nothing interesting to do here */
3846   } else {
3847     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3848       /* The mode is removed and we need to generate and distribute
3849          new channel key. Clients are not using private channel keys
3850          anymore after this. */
3851
3852       /* Re-generate channel key */
3853       if (!silc_server_create_channel_key(server, channel, 0))
3854         goto out;
3855       
3856       /* Send the channel key. This sends it to our local clients and if
3857          we are normal server to our router as well. */
3858       silc_server_send_channel_key(server, NULL, channel, 
3859                                    server->server_type == SILC_ROUTER ? 
3860                                    FALSE : !server->standalone);
3861
3862       cipher = channel->channel_key->cipher->name;
3863       hmac = (char *)silc_hmac_get_name(channel->hmac);
3864     }
3865   }
3866   
3867   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3868     /* User limit is set on channel */
3869     uint32 user_limit;
3870       
3871     /* Get user limit */
3872     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3873     if (!tmp) {
3874       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3875         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3876                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3877         goto out;
3878       }
3879     } else {
3880       SILC_GET32_MSB(user_limit, tmp);
3881       channel->user_limit = user_limit;
3882     }
3883   } else {
3884     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3885       /* User limit mode is unset. Remove user limit */
3886       channel->user_limit = 0;
3887   }
3888
3889   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3890     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3891       /* Passphrase has been set to channel */
3892       
3893       /* Get the passphrase */
3894       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3895       if (!tmp) {
3896         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3897                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3898         goto out;
3899       }
3900
3901       /* Save the passphrase */
3902       passphrase = channel->passphrase = strdup(tmp);
3903     }
3904   } else {
3905     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3906       /* Passphrase mode is unset. remove the passphrase */
3907       if (channel->passphrase) {
3908         silc_free(channel->passphrase);
3909         channel->passphrase = NULL;
3910       }
3911     }
3912   }
3913
3914   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3915     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3916       /* Cipher to use protect the traffic */
3917       SilcCipher newkey, oldkey;
3918
3919       /* Get cipher */
3920       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3921       if (!cipher) {
3922         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3924         goto out;
3925       }
3926
3927       /* Delete old cipher and allocate the new one */
3928       if (!silc_cipher_alloc(cipher, &newkey)) {
3929         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3930                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3931         goto out;
3932       }
3933
3934       oldkey = channel->channel_key;
3935       channel->channel_key = newkey;
3936
3937       /* Re-generate channel key */
3938       if (!silc_server_create_channel_key(server, channel, 0)) {
3939         /* We don't have new key, revert to old one */
3940         channel->channel_key = oldkey;
3941         goto out;
3942       }
3943
3944       /* Remove old channel key for good */
3945       silc_cipher_free(oldkey);
3946
3947       /* Send the channel key. This sends it to our local clients and if
3948          we are normal server to our router as well. */
3949       silc_server_send_channel_key(server, NULL, channel, 
3950                                    server->server_type == SILC_ROUTER ? 
3951                                    FALSE : !server->standalone);
3952     }
3953   } else {
3954     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3955       /* Cipher mode is unset. Remove the cipher and revert back to 
3956          default cipher */
3957       SilcCipher newkey, oldkey;
3958       cipher = channel->cipher;
3959
3960       /* Delete old cipher and allocate default one */
3961       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3962         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3964         goto out;
3965       }
3966
3967       oldkey = channel->channel_key;
3968       channel->channel_key = newkey;
3969
3970       /* Re-generate channel key */
3971       if (!silc_server_create_channel_key(server, channel, 0)) {
3972         /* We don't have new key, revert to old one */
3973         channel->channel_key = oldkey;
3974         goto out;
3975       }
3976       
3977       /* Remove old channel key for good */
3978       silc_cipher_free(oldkey);
3979
3980       /* Send the channel key. This sends it to our local clients and if
3981          we are normal server to our router as well. */
3982       silc_server_send_channel_key(server, NULL, channel, 
3983                                    server->server_type == SILC_ROUTER ? 
3984                                    FALSE : !server->standalone);
3985     }
3986   }
3987
3988   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3989     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3990       /* HMAC to use protect the traffic */
3991       unsigned char hash[32];
3992       SilcHmac newhmac;
3993
3994       /* Get hmac */
3995       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3996       if (!hmac) {
3997         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3998                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3999         goto out;
4000       }
4001
4002       /* Delete old hmac and allocate the new one */
4003       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4004         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4005                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4006         goto out;
4007       }
4008
4009       silc_hmac_free(channel->hmac);
4010       channel->hmac = newhmac;
4011
4012       /* Set the HMAC key out of current channel key. The client must do
4013          this locally. */
4014       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4015                      channel->key_len / 8, hash);
4016       silc_hmac_set_key(channel->hmac, hash, 
4017                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4018       memset(hash, 0, sizeof(hash));
4019     }
4020   } else {
4021     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4022       /* Hmac mode is unset. Remove the hmac and revert back to 
4023          default hmac */
4024       SilcHmac newhmac;
4025       unsigned char hash[32];
4026       hmac = channel->hmac_name;
4027
4028       /* Delete old hmac and allocate default one */
4029       silc_hmac_free(channel->hmac);
4030       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4031         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4032                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4033         goto out;
4034       }
4035
4036       silc_hmac_free(channel->hmac);
4037       channel->hmac = newhmac;
4038
4039       /* Set the HMAC key out of current channel key. The client must do
4040          this locally. */
4041       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4042                      channel->key_len / 8, 
4043                      hash);
4044       silc_hmac_set_key(channel->hmac, hash, 
4045                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4046       memset(hash, 0, sizeof(hash));
4047     }
4048   }
4049
4050   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4051     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4052       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4053         /* Set the founder authentication */
4054         SilcAuthPayload auth;
4055         
4056         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4057         if (!tmp) {
4058           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4059                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4060           goto out;
4061         }
4062
4063         auth = silc_auth_payload_parse(tmp, tmp_len);
4064         if (!auth) {
4065           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4066                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4067           goto out;
4068         }
4069
4070         /* Save the public key */
4071         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4072         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4073         silc_free(tmp);
4074         
4075         channel->founder_method = silc_auth_get_method(auth);
4076
4077         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4078           tmp = silc_auth_get_data(auth, &tmp_len);
4079           channel->founder_passwd = 
4080             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4081           memcpy(channel->founder_passwd, tmp, tmp_len);
4082           channel->founder_passwd_len = tmp_len;
4083         } else {
4084           /* Verify the payload before setting the mode */
4085           if (!silc_auth_verify(auth, channel->founder_method, 
4086                                 channel->founder_key, 0, idata->hash,
4087                                 client->id, SILC_ID_CLIENT)) {
4088             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4089                                                   SILC_STATUS_ERR_AUTH_FAILED);
4090             goto out;
4091           }
4092         }
4093
4094         silc_auth_payload_free(auth);
4095       }
4096     }
4097   } else {
4098     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4099       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4100         if (channel->founder_key)
4101           silc_pkcs_public_key_free(channel->founder_key);
4102         if (channel->founder_passwd) {
4103           silc_free(channel->founder_passwd);
4104           channel->founder_passwd = NULL;
4105         }
4106       }
4107     }
4108   }
4109
4110   /* Finally, set the mode */
4111   channel->mode = mode_mask;
4112
4113   /* Send CMODE_CHANGE notify. */
4114   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4115   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4116                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4117                                      cidp->data, cidp->len, 
4118                                      tmp_mask, 4,
4119                                      cipher, cipher ? strlen(cipher) : 0,
4120                                      hmac, hmac ? strlen(hmac) : 0,
4121                                      passphrase, passphrase ? 
4122                                      strlen(passphrase) : 0);
4123
4124   /* Set CMODE notify type to network */
4125   if (!server->standalone)
4126     silc_server_send_notify_cmode(server, server->router->connection,
4127                                   server->server_type == SILC_ROUTER ? 
4128                                   TRUE : FALSE, channel,
4129                                   mode_mask, client->id, SILC_ID_CLIENT,
4130                                   cipher, hmac, passphrase);
4131
4132   /* Send command reply to sender */
4133   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4134                                                 SILC_STATUS_OK, ident, 2,
4135                                                 2, tmp_id, tmp_len2,
4136                                                 3, tmp_mask, 4);
4137   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4138                           packet->data, packet->len, FALSE);
4139     
4140   silc_buffer_free(packet);
4141   silc_free(channel_id);
4142   silc_buffer_free(cidp);
4143
4144  out:
4145   silc_server_command_free(cmd);
4146 }
4147
4148 /* Server side of CUMODE command. Changes client's mode on a channel. */
4149
4150 SILC_SERVER_CMD_FUNC(cumode)
4151 {
4152   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4153   SilcServer server = cmd->server;
4154   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4155   SilcIDListData idata = (SilcIDListData)client;
4156   SilcChannelID *channel_id;
4157   SilcClientID *client_id;
4158   SilcChannelEntry channel;
4159   SilcClientEntry target_client;
4160   SilcChannelClientEntry chl;
4161   SilcBuffer packet, idp;
4162   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4163   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4164   int notify = FALSE;
4165   uint16 ident = silc_command_get_ident(cmd->payload);
4166
4167   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4168
4169   /* Get Channel ID */
4170   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4171   if (!tmp_ch_id) {
4172     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4173                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4174     goto out;
4175   }
4176   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4177   if (!channel_id) {
4178     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4179                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4180     goto out;
4181   }
4182
4183   /* Get channel entry */
4184   channel = silc_idlist_find_channel_by_id(server->local_list, 
4185                                            channel_id, NULL);
4186   if (!channel) {
4187     channel = silc_idlist_find_channel_by_id(server->global_list, 
4188                                              channel_id, NULL);
4189     if (!channel) {
4190       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4192       goto out;
4193     }
4194   }
4195
4196   /* Check whether sender is on the channel */
4197   if (!silc_server_client_on_channel(client, channel)) {
4198     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4199                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4200     goto out;
4201   }
4202
4203   /* Check that client has rights to change other's rights */
4204   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4205   sender_mask = chl->mode;
4206   
4207   /* Get the target client's channel mode mask */
4208   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4209   if (!tmp_mask) {
4210     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4212     goto out;
4213   }
4214   SILC_GET32_MSB(target_mask, tmp_mask);
4215
4216   /* Get target Client ID */
4217   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4218   if (!tmp_id) {
4219     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4220                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4221     goto out;
4222   }
4223   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4224   if (!client_id) {
4225     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4226                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4227     goto out;
4228   }
4229
4230   /* Get target client's entry */
4231   target_client = silc_idlist_find_client_by_id(server->local_list, 
4232                                                 client_id, TRUE, NULL);
4233   if (!target_client) {
4234     target_client = silc_idlist_find_client_by_id(server->global_list, 
4235                                                   client_id, TRUE, NULL);
4236   }
4237
4238   if (target_client != client &&
4239       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4240       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4241     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4242                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4243     goto out;
4244   }
4245
4246   /* Check whether target client is on the channel */
4247   if (target_client != client) {
4248     if (!silc_server_client_on_channel(target_client, channel)) {
4249       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4250                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4251       goto out;
4252     }
4253
4254     /* Get entry to the channel user list */
4255     silc_hash_table_find(channel->user_list, target_client, NULL, 
4256                          (void *)&chl);
4257   }
4258
4259   /* 
4260    * Change the mode 
4261    */
4262
4263   /* If the target client is founder, no one else can change their mode
4264      but themselves. */
4265   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4266     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4267                                           SILC_STATUS_ERR_NOT_YOU);
4268     goto out;
4269   }
4270
4271   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4272     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4273       /* The client tries to claim the founder rights. */
4274       unsigned char *tmp_auth;
4275       uint32 tmp_auth_len, auth_len;
4276       void *auth;
4277       
4278       if (target_client != client) {
4279         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4280                                               SILC_STATUS_ERR_NOT_YOU);
4281         goto out;
4282       }
4283
4284       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4285           !channel->founder_key || !idata->public_key ||
4286           !silc_pkcs_public_key_compare(channel->founder_key, 
4287                                         idata->public_key)) {
4288         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4289                                               SILC_STATUS_ERR_NOT_YOU);
4290         goto out;
4291       }
4292
4293       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4294       if (!tmp_auth) {
4295         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4296                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4297         goto out;
4298       }
4299
4300       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4301               (void *)channel->founder_passwd : (void *)channel->founder_key);
4302       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4303                   channel->founder_passwd_len : 0);
4304       
4305       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4306                                  channel->founder_method, auth, auth_len,
4307                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4308         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309                                               SILC_STATUS_ERR_AUTH_FAILED);
4310         goto out;
4311       }
4312       
4313       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4314       notify = TRUE;
4315     }
4316   } else {
4317     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4318       if (target_client == client) {
4319         /* Remove channel founder rights from itself */
4320         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4321         notify = TRUE;
4322       } else {
4323         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4324                                               SILC_STATUS_ERR_NOT_YOU);
4325         goto out;
4326       }
4327     }
4328   }
4329
4330   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4331     /* Promote to operator */
4332     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4333       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4334           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4335         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4336                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4337         goto out;
4338       }
4339
4340       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4341       notify = TRUE;
4342     }
4343   } else {
4344     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4345       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4346           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4347         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4348                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4349         goto out;
4350       }
4351
4352       /* Demote to normal user */
4353       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4354       notify = TRUE;
4355     }
4356   }
4357
4358   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4359   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4360
4361   /* Send notify to channel, notify only if mode was actually changed. */
4362   if (notify) {
4363     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4364                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4365                                        idp->data, idp->len,
4366                                        tmp_mask, 4, 
4367                                        tmp_id, tmp_len);
4368
4369     /* Set CUMODE notify type to network */
4370     if (!server->standalone)
4371       silc_server_send_notify_cumode(server, server->router->connection,
4372                                      server->server_type == SILC_ROUTER ? 
4373                                      TRUE : FALSE, channel,
4374                                      target_mask, client->id, 
4375                                      SILC_ID_CLIENT,
4376                                      target_client->id);
4377   }
4378
4379   /* Send command reply to sender */
4380   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4381                                                 SILC_STATUS_OK, ident, 3,
4382                                                 2, tmp_mask, 4,
4383                                                 3, tmp_ch_id, tmp_ch_len,
4384                                                 4, tmp_id, tmp_len);
4385   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4386                           packet->data, packet->len, FALSE);
4387     
4388   silc_buffer_free(packet);
4389   silc_free(channel_id);
4390   silc_free(client_id);
4391   silc_buffer_free(idp);
4392
4393  out:
4394   silc_server_command_free(cmd);
4395 }
4396
4397 /* Server side of KICK command. Kicks client out of channel. */
4398
4399 SILC_SERVER_CMD_FUNC(kick)
4400 {
4401   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4402   SilcServer server = cmd->server;
4403   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4404   SilcClientEntry target_client;
4405   SilcChannelID *channel_id;
4406   SilcClientID *client_id;
4407   SilcChannelEntry channel;
4408   SilcChannelClientEntry chl;
4409   SilcBuffer idp;
4410   uint32 tmp_len, target_idp_len;
4411   unsigned char *tmp, *comment, *target_idp;
4412
4413   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4414
4415   /* Get Channel ID */
4416   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4417   if (!tmp) {
4418     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4419                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4420     goto out;
4421   }
4422   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4423   if (!channel_id) {
4424     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4425                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4426     goto out;
4427   }
4428
4429   /* Get channel entry */
4430   channel = silc_idlist_find_channel_by_id(server->local_list, 
4431                                            channel_id, NULL);
4432   if (!channel) {
4433     channel = silc_idlist_find_channel_by_id(server->local_list, 
4434                                              channel_id, NULL);
4435     if (!channel) {
4436       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4437                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4438       goto out;
4439     }
4440   }
4441
4442   /* Check whether sender is on the channel */
4443   if (!silc_server_client_on_channel(client, channel)) {
4444     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4445                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4446     goto out;
4447   }
4448
4449   /* Check that the kicker is channel operator or channel founder */
4450   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4451   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4452     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4453                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4454     goto out;
4455   }
4456   
4457   /* Get target Client ID */
4458   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4459   if (!target_idp) {
4460     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4461                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4462     goto out;
4463   }
4464   client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4465   if (!client_id) {
4466     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4468     goto out;
4469   }
4470
4471   /* Get target client's entry */
4472   target_client = silc_idlist_find_client_by_id(server->local_list, 
4473                                                 client_id, TRUE, NULL);
4474   if (!target_client) {
4475     target_client = silc_idlist_find_client_by_id(server->global_list, 
4476                                                   client_id, TRUE, NULL);
4477   }
4478
4479   /* Check that the target client is not channel founder. Channel founder
4480      cannot be kicked from the channel. */
4481   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4482   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4483     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4484                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4485     goto out;
4486   }
4487   
4488   /* Check whether target client is on the channel */
4489   if (!silc_server_client_on_channel(target_client, channel)) {
4490     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4491                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4492     goto out;
4493   }
4494
4495   /* Get comment */
4496   tmp_len = 0;
4497   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4498   if (tmp_len > 128)
4499     comment = NULL;
4500
4501   /* Send command reply to sender */
4502   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4503                                         SILC_STATUS_OK);
4504
4505   /* Send KICKED notify to local clients on the channel */
4506   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4507   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4508                                      SILC_NOTIFY_TYPE_KICKED, 3,
4509                                      target_idp, target_idp_len,
4510                                      comment, comment ? strlen(comment) : 0,
4511                                      idp->data, idp->len);
4512   silc_buffer_free(idp);
4513
4514   /* Remove the client from the channel. If the channel does not exist
4515      after removing the client then the client kicked itself off the channel
4516      and we don't have to send anything after that. */
4517   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4518                                            target_client, FALSE))
4519     goto out;
4520
4521   /* Send KICKED notify to primary route */
4522   if (!server->standalone)
4523     silc_server_send_notify_kicked(server, server->router->connection,
4524                                    server->server_type == SILC_ROUTER ?
4525                                    TRUE : FALSE, channel,
4526                                    target_client->id, comment);
4527
4528   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4529     /* Re-generate channel key */
4530     if (!silc_server_create_channel_key(server, channel, 0))
4531       goto out;
4532     
4533     /* Send the channel key to the channel. The key of course is not sent
4534        to the client who was kicked off the channel. */
4535     silc_server_send_channel_key(server, target_client->connection, channel, 
4536                                  server->server_type == SILC_ROUTER ? 
4537                                  FALSE : !server->standalone);
4538   }
4539
4540  out:
4541   silc_server_command_free(cmd);
4542 }
4543
4544 /* Server side of OPER command. Client uses this comand to obtain server
4545    operator privileges to this server/router. */
4546
4547 SILC_SERVER_CMD_FUNC(oper)
4548 {
4549   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4550   SilcServer server = cmd->server;
4551   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4552   unsigned char *username, *auth;
4553   uint32 tmp_len;
4554   SilcServerConfigSectionAdminConnection *admin;
4555   SilcIDListData idata = (SilcIDListData)client;
4556
4557   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4558
4559   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4560     goto out;
4561
4562   /* Get the username */
4563   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4564   if (!username) {
4565     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4566                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4567     goto out;
4568   }
4569
4570   /* Get the admin configuration */
4571   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4572                                         username, client->nickname);
4573   if (!admin) {
4574     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4575                                           username, client->nickname);
4576     if (!admin) {
4577       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4578                                             SILC_STATUS_ERR_AUTH_FAILED);
4579       goto out;
4580     }
4581   }
4582
4583   /* Get the authentication payload */
4584   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4585   if (!auth) {
4586     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4587                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4588     goto out;
4589   }
4590
4591   /* Verify the authentication data */
4592   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4593                              admin->auth_data, admin->auth_data_len,
4594                              idata->hash, client->id, SILC_ID_CLIENT)) {
4595     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4596                                           SILC_STATUS_ERR_AUTH_FAILED);
4597     goto out;
4598   }
4599
4600   /* Client is now server operator */
4601   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4602
4603   /* Send UMODE change to primary router */
4604   if (!server->standalone)
4605     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4606                                   client->id, client->mode);
4607
4608   /* Send reply to the sender */
4609   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4610                                         SILC_STATUS_OK);
4611
4612  out:
4613   silc_server_command_free(cmd);
4614 }
4615
4616 /* Server side of SILCOPER command. Client uses this comand to obtain router
4617    operator privileges to this router. */
4618
4619 SILC_SERVER_CMD_FUNC(silcoper)
4620 {
4621   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4622   SilcServer server = cmd->server;
4623   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4624   unsigned char *username, *auth;
4625   uint32 tmp_len;
4626   SilcServerConfigSectionAdminConnection *admin;
4627   SilcIDListData idata = (SilcIDListData)client;
4628
4629   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4630
4631   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4632     goto out;
4633
4634   if (server->server_type != SILC_ROUTER) {
4635     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4636                                           SILC_STATUS_ERR_AUTH_FAILED);
4637     goto out;
4638   }
4639
4640   /* Get the username */
4641   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4642   if (!username) {
4643     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4644                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4645     goto out;
4646   }
4647
4648   /* Get the admin configuration */
4649   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4650                                         username, client->nickname);
4651   if (!admin) {
4652     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4653                                           username, client->nickname);
4654     if (!admin) {
4655       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4656                                             SILC_STATUS_ERR_AUTH_FAILED);
4657       goto out;
4658     }
4659   }
4660
4661   /* Get the authentication payload */
4662   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4663   if (!auth) {
4664     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4665                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4666     goto out;
4667   }
4668
4669   /* Verify the authentication data */
4670   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4671                              admin->auth_data, admin->auth_data_len,
4672                              idata->hash, client->id, SILC_ID_CLIENT)) {
4673     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674                                           SILC_STATUS_ERR_AUTH_FAILED);
4675     goto out;
4676   }
4677
4678   /* Client is now router operator */
4679   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4680
4681   /* Send UMODE change to primary router */
4682   if (!server->standalone)
4683     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4684                                   client->id, client->mode);
4685
4686   /* Send reply to the sender */
4687   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4688                                         SILC_STATUS_OK);
4689
4690  out:
4691   silc_server_command_free(cmd);
4692 }
4693
4694 /* Server side command of CONNECT. Connects us to the specified remote
4695    server or router. */
4696
4697 SILC_SERVER_CMD_FUNC(connect)
4698 {
4699   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4700   SilcServer server = cmd->server;
4701   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4702   unsigned char *tmp, *host;
4703   uint32 tmp_len;
4704   uint32 port = SILC_PORT;
4705
4706   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4707
4708   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4709     goto out;
4710
4711   /* Check whether client has the permissions. */
4712   if (client->mode == SILC_UMODE_NONE) {
4713     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4714                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4715     goto out;
4716   }
4717
4718   if (server->server_type == SILC_ROUTER && 
4719       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4720     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4721                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4722     goto out;
4723   }
4724
4725   /* Get the remote server */
4726   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4727   if (!host) {
4728     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4729                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4730     goto out;
4731   }
4732
4733   /* Get port */
4734   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4735   if (tmp)
4736     SILC_GET32_MSB(port, tmp);
4737
4738   /* Create the connection. It is done with timeout and is async. */
4739   silc_server_create_connection(server, host, port);
4740
4741   /* Send reply to the sender */
4742   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4743                                         SILC_STATUS_OK);
4744
4745  out:
4746   silc_server_command_free(cmd);
4747 }
4748
4749 /* Server side of command BAN. This is used to manage the ban list of the
4750    channel. To add clients and remove clients from the ban list. */
4751
4752 SILC_SERVER_CMD_FUNC(ban)
4753 {
4754   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4755   SilcServer server = cmd->server;
4756   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4757   SilcBuffer packet;
4758   SilcChannelEntry channel;
4759   SilcChannelClientEntry chl;
4760   SilcChannelID *channel_id = NULL;
4761   unsigned char *id, *add, *del;
4762   uint32 id_len, tmp_len;
4763   uint16 ident = silc_command_get_ident(cmd->payload);
4764
4765   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4766     goto out;
4767
4768   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4769
4770   /* Get Channel ID */
4771   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4772   if (id) {
4773     channel_id = silc_id_payload_parse_id(id, id_len);
4774     if (!channel_id) {
4775       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4776                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4777       goto out;
4778     }
4779   }
4780
4781   /* Get channel entry. The server must know about the channel since the
4782      client is expected to be on the channel. */
4783   channel = silc_idlist_find_channel_by_id(server->local_list, 
4784                                            channel_id, NULL);
4785   if (!channel) {
4786     channel = silc_idlist_find_channel_by_id(server->global_list, 
4787                                              channel_id, NULL);
4788     if (!channel) {
4789       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4790                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4791       goto out;
4792     }
4793   }
4794
4795   /* Check whether this client is on the channel */
4796   if (!silc_server_client_on_channel(client, channel)) {
4797     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4798                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4799     goto out;
4800   }
4801
4802   /* Get entry to the channel user list */
4803   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4804
4805   /* The client must be at least channel operator. */
4806   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4807     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4808                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4809     goto out;
4810   }
4811
4812   /* Get the new ban and add it to the ban list */
4813   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4814   if (add) {
4815     if (!channel->ban_list)
4816       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4817     else
4818       channel->ban_list = silc_realloc(channel->ban_list, 
4819                                        sizeof(*channel->ban_list) * 
4820                                        (tmp_len + 
4821                                         strlen(channel->ban_list) + 2));
4822     if (add[tmp_len - 1] == ',')
4823       add[tmp_len - 1] = '\0';
4824
4825     strncat(channel->ban_list, add, tmp_len);
4826     strncat(channel->ban_list, ",", 1);
4827   }
4828
4829   /* Get the ban to be removed and remove it from the list */
4830   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4831   if (del && channel->ban_list) {
4832     char *start, *end, *n;
4833
4834     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4835       silc_free(channel->ban_list);
4836       channel->ban_list = NULL;
4837     } else {
4838       start = strstr(channel->ban_list, del);
4839       if (start && strlen(start) >= tmp_len) {
4840         end = start + tmp_len;
4841         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4842         strncat(n, channel->ban_list, start - channel->ban_list);
4843         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4844                              end) - 1);
4845         silc_free(channel->ban_list);
4846         channel->ban_list = n;
4847       }
4848     }
4849   }
4850
4851   /* Send the BAN notify type to our primary router. */
4852   if (!server->standalone && (add || del))
4853     silc_server_send_notify_ban(server, server->router->connection,
4854                                 server->server_type == SILC_ROUTER ?
4855                                 TRUE : FALSE, channel, add, del);
4856
4857   /* Send the reply back to the client */
4858   packet = 
4859     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4860                                          SILC_STATUS_OK, ident, 2,
4861                                          2, id, id_len,
4862                                          3, channel->ban_list, 
4863                                          channel->ban_list ? 
4864                                          strlen(channel->ban_list) - 1 : 0);
4865   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4866                           packet->data, packet->len, FALSE);
4867     
4868   silc_buffer_free(packet);
4869
4870  out:
4871   silc_free(channel_id);
4872   silc_server_command_free(cmd);
4873 }
4874
4875 /* Server side command of CLOSE. Closes connection to a specified server. */
4876  
4877 SILC_SERVER_CMD_FUNC(close)
4878 {
4879   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4880   SilcServer server = cmd->server;
4881   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4882   SilcServerEntry server_entry;
4883   SilcSocketConnection sock;
4884   unsigned char *tmp;
4885   uint32 tmp_len;
4886   unsigned char *name;
4887   uint32 port = SILC_PORT;
4888
4889   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4890
4891   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4892     goto out;
4893
4894   /* Check whether client has the permissions. */
4895   if (client->mode == SILC_UMODE_NONE) {
4896     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4897                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4898     goto out;
4899   }
4900
4901   /* Get the remote server */
4902   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4903   if (!name) {
4904     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4905                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4906     goto out;
4907   }
4908
4909   /* Get port */
4910   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4911   if (tmp)
4912     SILC_GET32_MSB(port, tmp);
4913
4914   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4915                                                  name, port, FALSE, NULL);
4916   if (!server_entry)
4917     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4918                                                    name, port, FALSE, NULL);
4919   if (!server_entry) {
4920     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4921                                           SILC_STATUS_ERR_NO_SERVER_ID);
4922     goto out;
4923   }
4924
4925   /* Send reply to the sender */
4926   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4927                                         SILC_STATUS_OK);
4928
4929   /* Close the connection to the server */
4930   sock = (SilcSocketConnection)server_entry->connection;
4931
4932   /* If we shutdown primary router connection manually then don't trigger
4933      any reconnect or backup router connections, by setting the router
4934      to NULL here. */
4935   if (server->router == server_entry) {
4936     server->id_entry->router = NULL;
4937     server->router = NULL;
4938     server->standalone = TRUE;
4939   }
4940   silc_server_free_sock_user_data(server, sock, NULL);
4941   silc_server_close_connection(server, sock);
4942   
4943  out:
4944   silc_server_command_free(cmd);
4945 }
4946
4947 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4948    active connections. */
4949  
4950 SILC_SERVER_CMD_FUNC(shutdown)
4951 {
4952   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4953   SilcServer server = cmd->server;
4954   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4955
4956   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4957
4958   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4959     goto out;
4960
4961   /* Check whether client has the permission. */
4962   if (client->mode == SILC_UMODE_NONE) {
4963     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4964                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4965     goto out;
4966   }
4967
4968   /* Send reply to the sender */
4969   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4970                                         SILC_STATUS_OK);
4971
4972   /* Then, gracefully, or not, bring the server down. */
4973   silc_server_stop(server);
4974   exit(0);
4975
4976  out:
4977   silc_server_command_free(cmd);
4978 }
4979  
4980 /* Server side command of LEAVE. Removes client from a channel. */
4981
4982 SILC_SERVER_CMD_FUNC(leave)
4983 {
4984   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4985   SilcServer server = cmd->server;
4986   SilcSocketConnection sock = cmd->sock;
4987   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4988   SilcChannelID *id = NULL;
4989   SilcChannelEntry channel;
4990   uint32 len;
4991   unsigned char *tmp;
4992
4993   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4994
4995   /* Get Channel ID */
4996   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4997   if (!tmp) {
4998     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4999                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5000     goto out;
5001   }
5002   id = silc_id_payload_parse_id(tmp, len);
5003   if (!id) {
5004     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5005                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5006     goto out;
5007   }
5008
5009   /* Get channel entry */
5010   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5011   if (!channel) {
5012     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5013     if (!channel) {
5014       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5015                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5016       goto out;
5017     }
5018   }
5019
5020   /* Check whether this client is on the channel */
5021   if (!silc_server_client_on_channel(id_entry, channel)) {
5022     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5023                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
5024     goto out;
5025   }
5026
5027   /* Notify routers that they should remove this client from their list
5028      of clients on the channel. Send LEAVE notify type. */
5029   if (!server->standalone)
5030     silc_server_send_notify_leave(server, server->router->connection,
5031                                   server->server_type == SILC_ROUTER ?
5032                                   TRUE : FALSE, channel, id_entry->id);
5033
5034   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5035                                         SILC_STATUS_OK);
5036
5037   /* Remove client from channel */
5038   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5039                                            TRUE))
5040     /* If the channel does not exist anymore we won't send anything */
5041     goto out;
5042
5043   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5044     /* Re-generate channel key */
5045     if (!silc_server_create_channel_key(server, channel, 0))
5046       goto out;
5047
5048     /* Send the channel key */
5049     silc_server_send_channel_key(server, NULL, channel, 
5050                                  server->server_type == SILC_ROUTER ? 
5051                                  FALSE : !server->standalone);
5052   }
5053
5054  out:
5055   silc_free(id);
5056   silc_server_command_free(cmd);
5057 }
5058
5059 /* Server side of command USERS. Resolves clients and their USERS currently
5060    joined on the requested channel. The list of Client ID's and their modes
5061    on the channel is sent back. */
5062
5063 SILC_SERVER_CMD_FUNC(users)
5064 {
5065   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5066   SilcServer server = cmd->server;
5067   SilcChannelEntry channel;
5068   SilcChannelID *id = NULL;
5069   SilcBuffer packet, idp;
5070   unsigned char *channel_id;
5071   uint32 channel_id_len;
5072   SilcBuffer client_id_list;
5073   SilcBuffer client_mode_list;
5074   unsigned char lc[4];
5075   uint32 list_count = 0;
5076   uint16 ident = silc_command_get_ident(cmd->payload);
5077   char *channel_name;
5078
5079   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5080
5081   /* Get Channel ID */
5082   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5083
5084   /* Get channel name */
5085   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5086
5087   if (!channel_id && !channel_name) {
5088     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5089                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5090     goto out;
5091   }
5092
5093   if (channel_id) {
5094     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5095     if (!id) {
5096       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5097                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5098       goto out;
5099     }
5100   }
5101
5102   /* If we are server and we don't know about this channel we will send
5103      the command to our router. If we know about the channel then we also
5104      have the list of users already. */
5105   if (id)
5106     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5107   else
5108     channel = silc_idlist_find_channel_by_name(server->local_list, 
5109                                                channel_name, NULL);
5110
5111   if (!channel || channel->disabled) {
5112     if (server->server_type != SILC_ROUTER && !server->standalone &&
5113         !cmd->pending) {
5114       SilcBuffer tmpbuf;
5115       
5116       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5117       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5118       
5119       /* Send USERS command */
5120       silc_server_packet_send(server, server->router->connection,
5121                               SILC_PACKET_COMMAND, cmd->packet->flags,
5122                               tmpbuf->data, tmpbuf->len, TRUE);
5123       
5124       /* Reprocess this packet after received reply */
5125       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5126                                   silc_command_get_ident(cmd->payload),
5127                                   silc_server_command_users,
5128                                   silc_server_command_dup(cmd));
5129       cmd->pending = TRUE;
5130       silc_command_set_ident(cmd->payload, ident);
5131       silc_buffer_free(tmpbuf);
5132       silc_free(id);
5133       goto out;
5134     }
5135
5136     /* Check the global list as well. */
5137     if (id)
5138       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5139     else
5140       channel = silc_idlist_find_channel_by_name(server->global_list, 
5141                                                  channel_name, NULL);
5142     if (!channel) {
5143       /* Channel really does not exist */
5144       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5145                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5146       goto out;
5147     }
5148   }
5149
5150   /* If the channel is private or secret do not send anything, unless the
5151      user requesting this command is on the channel. */
5152   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5153     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5154         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5155       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5156                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5157       goto out;
5158     }
5159   } else {
5160     if (channel->mode & 
5161         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5162       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5163                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5164       goto out;
5165     }
5166   }
5167
5168   /* Get the users list */
5169   silc_server_get_users_on_channel(server, channel, &client_id_list,
5170                                    &client_mode_list, &list_count);
5171
5172   /* List count */
5173   SILC_PUT32_MSB(list_count, lc);
5174
5175   /* Send reply */
5176   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5177   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5178                                                 SILC_STATUS_OK, ident, 4,
5179                                                 2, idp->data, idp->len,
5180                                                 3, lc, 4,
5181                                                 4, client_id_list->data,
5182                                                 client_id_list->len,
5183                                                 5, client_mode_list->data,
5184                                                 client_mode_list->len);
5185   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5186                           packet->data, packet->len, FALSE);
5187     
5188   silc_buffer_free(idp);
5189   silc_buffer_free(packet);
5190   silc_buffer_free(client_id_list);
5191   silc_buffer_free(client_mode_list);
5192   silc_free(id);
5193
5194  out:
5195   silc_server_command_free(cmd);
5196 }
5197
5198 /* Server side of command GETKEY. This fetches the client's public key
5199    from the server where to the client is connected. */
5200
5201 SILC_SERVER_CMD_FUNC(getkey)
5202 {
5203   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5204   SilcServer server = cmd->server;
5205   SilcBuffer packet;
5206   SilcClientEntry client;
5207   SilcServerEntry server_entry;
5208   SilcClientID *client_id = NULL;
5209   SilcServerID *server_id = NULL;
5210   SilcIDPayload idp = NULL;
5211   uint16 ident = silc_command_get_ident(cmd->payload);
5212   unsigned char *tmp, *pkdata;
5213   uint32 tmp_len, pklen;
5214   SilcBuffer pk = NULL;
5215   SilcIdType id_type;
5216
5217   SILC_LOG_DEBUG(("Start"));
5218
5219   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5220   if (!tmp) {
5221     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5222                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5223     goto out;
5224   }
5225   idp = silc_id_payload_parse(tmp, tmp_len);
5226   if (!idp) {
5227     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5228                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5229     goto out;
5230   }
5231
5232   id_type = silc_id_payload_get_type(idp);
5233   if (id_type == SILC_ID_CLIENT) {
5234     client_id = silc_id_payload_get_id(idp);
5235
5236     /* If the client is not found from local list there is no chance it
5237        would be locally connected client so send the command further. */
5238     client = silc_idlist_find_client_by_id(server->local_list, 
5239                                            client_id, TRUE, NULL);
5240     if (!client)
5241       client = silc_idlist_find_client_by_id(server->global_list, 
5242                                              client_id, TRUE, NULL);
5243     
5244     if ((!client && !cmd->pending && !server->standalone) ||
5245         (client && !client->connection && !cmd->pending) ||
5246         (client && !client->data.public_key && !cmd->pending)) {
5247       SilcBuffer tmpbuf;
5248       uint16 old_ident;
5249       SilcSocketConnection dest_sock;
5250       
5251       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5252                                                client_id, NULL);
5253       if (!dest_sock)
5254         goto out;
5255       
5256       old_ident = silc_command_get_ident(cmd->payload);
5257       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5258       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5259       
5260       silc_server_packet_send(server, dest_sock,
5261                               SILC_PACKET_COMMAND, cmd->packet->flags,
5262                               tmpbuf->data, tmpbuf->len, TRUE);
5263       
5264       /* Reprocess this packet after received reply from router */
5265       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5266                                   silc_command_get_ident(cmd->payload),
5267                                   silc_server_command_getkey,
5268                                   silc_server_command_dup(cmd));
5269       cmd->pending = TRUE;
5270       silc_command_set_ident(cmd->payload, old_ident);
5271       silc_buffer_free(tmpbuf);
5272       goto out;
5273     }
5274
5275     if (!client) {
5276       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5277                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5278       goto out;
5279     }
5280
5281     /* The client is locally connected, just get the public key and
5282        send it back. If they key does not exist then do not send it, 
5283        send just OK reply */
5284     if (!client->data.public_key) {
5285       pkdata = NULL;
5286       pklen = 0;
5287     } else {
5288       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5289       pk = silc_buffer_alloc(4 + tmp_len);
5290       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5291       silc_buffer_format(pk,
5292                          SILC_STR_UI_SHORT(tmp_len),
5293                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5294                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5295                          SILC_STR_END);
5296       silc_free(tmp);
5297       pkdata = pk->data;
5298       pklen = pk->len;
5299     }
5300   } else if (id_type == SILC_ID_SERVER) {
5301     server_id = silc_id_payload_get_id(idp);
5302
5303     /* If the server is not found from local list there is no chance it
5304        would be locally connected server so send the command further. */
5305     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5306                                                  server_id, TRUE, NULL);
5307     if (!server_entry)
5308       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5309                                                    server_id, TRUE, NULL);
5310     
5311     if (server_entry != server->id_entry &&
5312         ((!server_entry && !cmd->pending && !server->standalone) ||
5313          (server_entry && !server_entry->connection && !cmd->pending &&
5314           !server->standalone) ||
5315          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5316           !server->standalone))) {
5317       SilcBuffer tmpbuf;
5318       uint16 old_ident;
5319       
5320       old_ident = silc_command_get_ident(cmd->payload);
5321       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5322       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5323       
5324       silc_server_packet_send(server, server->router->connection,
5325                               SILC_PACKET_COMMAND, cmd->packet->flags,
5326                               tmpbuf->data, tmpbuf->len, TRUE);
5327       
5328       /* Reprocess this packet after received reply from router */
5329       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5330                                   silc_command_get_ident(cmd->payload),
5331                                   silc_server_command_getkey,
5332                                   silc_server_command_dup(cmd));
5333       cmd->pending = TRUE;
5334       
5335       silc_command_set_ident(cmd->payload, old_ident);
5336       silc_buffer_free(tmpbuf);
5337       goto out;
5338     }
5339
5340     if (!server_entry) {
5341       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5342                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5343       goto out;
5344     }
5345
5346     /* If they key does not exist then do not send it, send just OK reply */
5347     if (!server_entry->data.public_key) {
5348       pkdata = NULL;
5349       pklen = 0;
5350     } else {
5351       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5352                                         &tmp_len);
5353       pk = silc_buffer_alloc(4 + tmp_len);
5354       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5355       silc_buffer_format(pk,
5356                          SILC_STR_UI_SHORT(tmp_len),
5357                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5358                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5359                          SILC_STR_END);
5360       silc_free(tmp);
5361       pkdata = pk->data;
5362       pklen = pk->len;
5363     }
5364   } else {
5365     goto out;
5366   }
5367
5368   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5369   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5370                                                 SILC_STATUS_OK, ident, 
5371                                                 pkdata ? 2 : 1,
5372                                                 2, tmp, tmp_len,
5373                                                 3, pkdata, pklen);
5374   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5375                           packet->data, packet->len, FALSE);
5376   silc_buffer_free(packet);
5377
5378   if (pk)
5379     silc_buffer_free(pk);
5380
5381  out:
5382   if (idp)
5383     silc_id_payload_free(idp);
5384   silc_free(client_id);
5385   silc_free(server_id);
5386   silc_server_command_free(cmd);
5387 }