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