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