Added support for multiple PublicKey instances in the config
[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   SilcPublicKey cached_key;
4587
4588   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4589
4590   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4591     goto out;
4592
4593   /* Get the username */
4594   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4595   if (!username) {
4596     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4597                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4598     goto out;
4599   }
4600
4601   /* Get the admin configuration */
4602   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4603                                         username, client->nickname);
4604   if (!admin) {
4605     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4606                                           username, client->nickname);
4607     if (!admin) {
4608       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4609                                             SILC_STATUS_ERR_AUTH_FAILED);
4610       goto out;
4611     }
4612   }
4613
4614   /* Get the authentication payload */
4615   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4616   if (!auth) {
4617     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4618                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4619     goto out;
4620   }
4621
4622   /* Verify the authentication data. If both passphrase and public key
4623      is set then try both of them. */
4624   if (admin->passphrase)
4625     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4626                                    admin->passphrase, admin->passphrase_len,
4627                                    idata->hash, client->id, SILC_ID_CLIENT);
4628   if (!result && admin->publickeys) {
4629     cached_key = silc_server_get_public_key(server, admin->publickeys);
4630     if (!cached_key)
4631       goto out;
4632     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4633                                    cached_key, 0, idata->hash, 
4634                                    client->id, SILC_ID_CLIENT);
4635   }
4636   if (!result) {
4637     /* Authentication failed */
4638     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4639                                           SILC_STATUS_ERR_AUTH_FAILED);
4640     goto out;
4641   }
4642
4643   /* Client is now server operator */
4644   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4645
4646   /* Update statistics */
4647   if (client->connection)
4648     server->stat.my_server_ops++;
4649   if (server->server_type == SILC_ROUTER)
4650     server->stat.server_ops++;
4651
4652   /* Send UMODE change to primary router */
4653   if (!server->standalone)
4654     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4655                                   client->id, client->mode);
4656
4657   /* Send reply to the sender */
4658   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4659                                         SILC_STATUS_OK);
4660
4661  out:
4662   silc_server_command_free(cmd);
4663 }
4664
4665 /* Server side of SILCOPER command. Client uses this comand to obtain router
4666    operator privileges to this router. */
4667
4668 SILC_SERVER_CMD_FUNC(silcoper)
4669 {
4670   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4671   SilcServer server = cmd->server;
4672   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4673   unsigned char *username, *auth;
4674   SilcUInt32 tmp_len;
4675   SilcServerConfigAdmin *admin;
4676   SilcIDListData idata = (SilcIDListData)client;
4677   bool result = FALSE;
4678   SilcPublicKey cached_key;
4679
4680   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4681
4682   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4683     goto out;
4684
4685   if (server->server_type != SILC_ROUTER) {
4686     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4687                                           SILC_STATUS_ERR_AUTH_FAILED);
4688     goto out;
4689   }
4690
4691   /* Get the username */
4692   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4693   if (!username) {
4694     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4695                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4696     goto out;
4697   }
4698
4699   /* Get the admin configuration */
4700   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4701                                         username, client->nickname);
4702   if (!admin) {
4703     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4704                                           username, client->nickname);
4705     if (!admin) {
4706       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4707                                             SILC_STATUS_ERR_AUTH_FAILED);
4708       goto out;
4709     }
4710   }
4711
4712   /* Get the authentication payload */
4713   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4714   if (!auth) {
4715     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4716                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4717     goto out;
4718   }
4719
4720   /* Verify the authentication data. If both passphrase and public key
4721      is set then try both of them. */
4722   if (admin->passphrase)
4723     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4724                                    admin->passphrase, admin->passphrase_len,
4725                                    idata->hash, client->id, SILC_ID_CLIENT);
4726   if (!result && admin->publickeys) {
4727     cached_key = silc_server_get_public_key(server, admin->publickeys);
4728     if (!cached_key)
4729       goto out;
4730     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4731                                    cached_key, 0, idata->hash, 
4732                                    client->id, SILC_ID_CLIENT);
4733   }
4734   if (!result) {
4735     /* Authentication failed */
4736     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4737                                           SILC_STATUS_ERR_AUTH_FAILED);
4738     goto out;
4739   }
4740
4741   /* Client is now router operator */
4742   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4743
4744   /* Update statistics */
4745   if (client->connection)
4746     server->stat.my_router_ops++;
4747   if (server->server_type == SILC_ROUTER)
4748     server->stat.router_ops++;
4749
4750   /* Send UMODE change to primary router */
4751   if (!server->standalone)
4752     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4753                                   client->id, client->mode);
4754
4755   /* Send reply to the sender */
4756   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4757                                         SILC_STATUS_OK);
4758
4759  out:
4760   silc_server_command_free(cmd);
4761 }
4762
4763 /* Server side command of CONNECT. Connects us to the specified remote
4764    server or router. */
4765
4766 SILC_SERVER_CMD_FUNC(connect)
4767 {
4768   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4769   SilcServer server = cmd->server;
4770   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4771   unsigned char *tmp, *host;
4772   SilcUInt32 tmp_len;
4773   SilcUInt32 port = SILC_PORT;
4774
4775   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4776
4777   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4778     goto out;
4779
4780   /* Check whether client has the permissions. */
4781   if (client->mode == SILC_UMODE_NONE) {
4782     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4783                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4784     goto out;
4785   }
4786
4787   if (server->server_type == SILC_ROUTER && 
4788       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4789     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4790                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4791     goto out;
4792   }
4793
4794   /* Get the remote server */
4795   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4796   if (!host) {
4797     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4798                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4799     goto out;
4800   }
4801
4802   /* Get port */
4803   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4804   if (tmp)
4805     SILC_GET32_MSB(port, tmp);
4806
4807   /* Create the connection. It is done with timeout and is async. */
4808   silc_server_create_connection(server, host, port);
4809
4810   /* Send reply to the sender */
4811   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4812                                         SILC_STATUS_OK);
4813
4814  out:
4815   silc_server_command_free(cmd);
4816 }
4817
4818 /* Server side of command BAN. This is used to manage the ban list of the
4819    channel. To add clients and remove clients from the ban list. */
4820
4821 SILC_SERVER_CMD_FUNC(ban)
4822 {
4823   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4824   SilcServer server = cmd->server;
4825   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4826   SilcBuffer packet;
4827   SilcChannelEntry channel;
4828   SilcChannelClientEntry chl;
4829   SilcChannelID *channel_id = NULL;
4830   unsigned char *id, *add, *del;
4831   SilcUInt32 id_len, tmp_len;
4832   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4833
4834   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4835     goto out;
4836
4837   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4838
4839   /* Get Channel ID */
4840   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4841   if (id) {
4842     channel_id = silc_id_payload_parse_id(id, id_len);
4843     if (!channel_id) {
4844       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4845                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4846       goto out;
4847     }
4848   }
4849
4850   /* Get channel entry. The server must know about the channel since the
4851      client is expected to be on the channel. */
4852   channel = silc_idlist_find_channel_by_id(server->local_list, 
4853                                            channel_id, NULL);
4854   if (!channel) {
4855     channel = silc_idlist_find_channel_by_id(server->global_list, 
4856                                              channel_id, NULL);
4857     if (!channel) {
4858       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4859                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4860       goto out;
4861     }
4862   }
4863
4864   /* Check whether this client is on the channel */
4865   if (!silc_server_client_on_channel(client, channel)) {
4866     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4867                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4868     goto out;
4869   }
4870
4871   /* Get entry to the channel user list */
4872   if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4873     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4874                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4875     goto out;
4876   }
4877
4878   /* The client must be at least channel operator. */
4879   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4880     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4881                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4882     goto out;
4883   }
4884
4885   /* Get the new ban and add it to the ban list */
4886   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4887   if (add) {
4888     if (!channel->ban_list)
4889       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4890     else
4891       channel->ban_list = silc_realloc(channel->ban_list, 
4892                                        sizeof(*channel->ban_list) * 
4893                                        (tmp_len + 
4894                                         strlen(channel->ban_list) + 2));
4895     if (add[tmp_len - 1] == ',')
4896       add[tmp_len - 1] = '\0';
4897
4898     strncat(channel->ban_list, add, tmp_len);
4899     strncat(channel->ban_list, ",", 1);
4900   }
4901
4902   /* Get the ban to be removed and remove it from the list */
4903   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4904   if (del && channel->ban_list) {
4905     char *start, *end, *n;
4906
4907     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4908       silc_free(channel->ban_list);
4909       channel->ban_list = NULL;
4910     } else {
4911       start = strstr(channel->ban_list, del);
4912       if (start && strlen(start) >= tmp_len) {
4913         end = start + tmp_len;
4914         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4915         strncat(n, channel->ban_list, start - channel->ban_list);
4916         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4917                              end) - 1);
4918         silc_free(channel->ban_list);
4919         channel->ban_list = n;
4920       }
4921     }
4922   }
4923
4924   /* Send the BAN notify type to our primary router. */
4925   if (!server->standalone && (add || del))
4926     silc_server_send_notify_ban(server, server->router->connection,
4927                                 server->server_type == SILC_ROUTER ?
4928                                 TRUE : FALSE, channel, add, del);
4929
4930   /* Send the reply back to the client */
4931   packet = 
4932     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4933                                          SILC_STATUS_OK, ident, 2,
4934                                          2, id, id_len,
4935                                          3, channel->ban_list, 
4936                                          channel->ban_list ? 
4937                                          strlen(channel->ban_list) -1 : 0);
4938   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4939                           packet->data, packet->len, FALSE);
4940     
4941   silc_buffer_free(packet);
4942
4943  out:
4944   silc_free(channel_id);
4945   silc_server_command_free(cmd);
4946 }
4947
4948 /* Server side command of CLOSE. Closes connection to a specified server. */
4949  
4950 SILC_SERVER_CMD_FUNC(close)
4951 {
4952   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4953   SilcServer server = cmd->server;
4954   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4955   SilcServerEntry server_entry;
4956   SilcSocketConnection sock;
4957   unsigned char *tmp;
4958   SilcUInt32 tmp_len;
4959   unsigned char *name;
4960   SilcUInt32 port = SILC_PORT;
4961
4962   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4963
4964   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4965     goto out;
4966
4967   /* Check whether client has the permissions. */
4968   if (client->mode == SILC_UMODE_NONE) {
4969     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4970                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4971     goto out;
4972   }
4973
4974   /* Get the remote server */
4975   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4976   if (!name) {
4977     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4978                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4979     goto out;
4980   }
4981
4982   /* Get port */
4983   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4984   if (tmp)
4985     SILC_GET32_MSB(port, tmp);
4986
4987   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4988                                                  name, port, FALSE, NULL);
4989   if (!server_entry)
4990     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4991                                                    name, port, FALSE, NULL);
4992   if (!server_entry) {
4993     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4994                                           SILC_STATUS_ERR_NO_SERVER_ID);
4995     goto out;
4996   }
4997
4998   /* Send reply to the sender */
4999   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
5000                                         SILC_STATUS_OK);
5001
5002   /* Close the connection to the server */
5003   sock = (SilcSocketConnection)server_entry->connection;
5004
5005   /* If we shutdown primary router connection manually then don't trigger
5006      any reconnect or backup router connections, by setting the router
5007      to NULL here. */
5008   if (server->router == server_entry) {
5009     server->id_entry->router = NULL;
5010     server->router = NULL;
5011     server->standalone = TRUE;
5012   }
5013   silc_server_free_sock_user_data(server, sock, NULL);
5014   silc_server_close_connection(server, sock);
5015   
5016  out:
5017   silc_server_command_free(cmd);
5018 }
5019
5020 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5021    active connections. */
5022  
5023 SILC_SERVER_CMD_FUNC(shutdown)
5024 {
5025   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5026   SilcServer server = cmd->server;
5027   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5028
5029   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5030
5031   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5032     goto out;
5033
5034   /* Check whether client has the permission. */
5035   if (client->mode == SILC_UMODE_NONE) {
5036     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5037                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5038     goto out;
5039   }
5040
5041   /* Send reply to the sender */
5042   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5043                                         SILC_STATUS_OK);
5044
5045   /* Then, gracefully, or not, bring the server down. */
5046   silc_server_stop(server);
5047   exit(0);
5048
5049  out:
5050   silc_server_command_free(cmd);
5051 }
5052  
5053 /* Server side command of LEAVE. Removes client from a channel. */
5054
5055 SILC_SERVER_CMD_FUNC(leave)
5056 {
5057   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5058   SilcServer server = cmd->server;
5059   SilcSocketConnection sock = cmd->sock;
5060   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5061   SilcChannelID *id = NULL;
5062   SilcChannelEntry channel;
5063   SilcUInt32 len;
5064   unsigned char *tmp;
5065
5066   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5067
5068   /* Get Channel ID */
5069   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5070   if (!tmp) {
5071     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5072                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5073     goto out;
5074   }
5075   id = silc_id_payload_parse_id(tmp, len);
5076   if (!id) {
5077     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5078                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5079     goto out;
5080   }
5081
5082   /* Get channel entry */
5083   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5084   if (!channel) {
5085     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5086     if (!channel) {
5087       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5088                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5089       goto out;
5090     }
5091   }
5092
5093   /* Check whether this client is on the channel */
5094   if (!silc_server_client_on_channel(id_entry, channel)) {
5095     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5096                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
5097     goto out;
5098   }
5099
5100   /* Notify routers that they should remove this client from their list
5101      of clients on the channel. Send LEAVE notify type. */
5102   if (!server->standalone)
5103     silc_server_send_notify_leave(server, server->router->connection,
5104                                   server->server_type == SILC_ROUTER ?
5105                                   TRUE : FALSE, channel, id_entry->id);
5106
5107   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5108                                         SILC_STATUS_OK);
5109
5110   /* Remove client from channel */
5111   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5112                                            TRUE))
5113     /* If the channel does not exist anymore we won't send anything */
5114     goto out;
5115
5116   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5117     /* Re-generate channel key */
5118     if (!silc_server_create_channel_key(server, channel, 0))
5119       goto out;
5120
5121     /* Send the channel key */
5122     silc_server_send_channel_key(server, NULL, channel, 
5123                                  server->server_type == SILC_ROUTER ? 
5124                                  FALSE : !server->standalone);
5125   }
5126
5127  out:
5128   silc_free(id);
5129   silc_server_command_free(cmd);
5130 }
5131
5132 /* Server side of command USERS. Resolves clients and their USERS currently
5133    joined on the requested channel. The list of Client ID's and their modes
5134    on the channel is sent back. */
5135
5136 SILC_SERVER_CMD_FUNC(users)
5137 {
5138   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5139   SilcServer server = cmd->server;
5140   SilcChannelEntry channel;
5141   SilcChannelID *id = NULL;
5142   SilcBuffer packet, idp;
5143   unsigned char *channel_id;
5144   SilcUInt32 channel_id_len;
5145   SilcBuffer client_id_list;
5146   SilcBuffer client_mode_list;
5147   unsigned char lc[4];
5148   SilcUInt32 list_count = 0;
5149   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5150   char *channel_name;
5151
5152   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5153
5154   /* Get Channel ID */
5155   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5156
5157   /* Get channel name */
5158   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5159
5160   if (!channel_id && !channel_name) {
5161     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5162                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5163     goto out;
5164   }
5165
5166   if (channel_id) {
5167     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5168     if (!id) {
5169       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5170                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5171       goto out;
5172     }
5173   }
5174
5175   /* If we are server and we don't know about this channel we will send
5176      the command to our router. If we know about the channel then we also
5177      have the list of users already. */
5178   if (id)
5179     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5180   else
5181     channel = silc_idlist_find_channel_by_name(server->local_list, 
5182                                                channel_name, NULL);
5183
5184   if (!channel || channel->disabled) {
5185     if (server->server_type != SILC_ROUTER && !server->standalone &&
5186         !cmd->pending) {
5187       SilcBuffer tmpbuf;
5188       
5189       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5190       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5191       
5192       /* Send USERS command */
5193       silc_server_packet_send(server, server->router->connection,
5194                               SILC_PACKET_COMMAND, cmd->packet->flags,
5195                               tmpbuf->data, tmpbuf->len, TRUE);
5196       
5197       /* Reprocess this packet after received reply */
5198       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5199                                   silc_command_get_ident(cmd->payload),
5200                                   silc_server_command_users,
5201                                   silc_server_command_dup(cmd));
5202       cmd->pending = TRUE;
5203       silc_command_set_ident(cmd->payload, ident);
5204       silc_buffer_free(tmpbuf);
5205       silc_free(id);
5206       goto out;
5207     }
5208
5209     /* Check the global list as well. */
5210     if (id)
5211       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5212     else
5213       channel = silc_idlist_find_channel_by_name(server->global_list, 
5214                                                  channel_name, NULL);
5215     if (!channel) {
5216       /* Channel really does not exist */
5217       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5218                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5219       goto out;
5220     }
5221   }
5222
5223   /* If the channel is private or secret do not send anything, unless the
5224      user requesting this command is on the channel. */
5225   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5226     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5227         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5228       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5229                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5230       goto out;
5231     }
5232   } else {
5233     if (channel->mode & 
5234         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5235       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5236                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5237       goto out;
5238     }
5239   }
5240
5241   /* Get the users list */
5242   silc_server_get_users_on_channel(server, channel, &client_id_list,
5243                                    &client_mode_list, &list_count);
5244
5245   /* List count */
5246   SILC_PUT32_MSB(list_count, lc);
5247
5248   /* Send reply */
5249   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5250   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5251                                                 SILC_STATUS_OK, ident, 4,
5252                                                 2, idp->data, idp->len,
5253                                                 3, lc, 4,
5254                                                 4, client_id_list->data,
5255                                                 client_id_list->len,
5256                                                 5, client_mode_list->data,
5257                                                 client_mode_list->len);
5258   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5259                           packet->data, packet->len, FALSE);
5260     
5261   silc_buffer_free(idp);
5262   silc_buffer_free(packet);
5263   silc_buffer_free(client_id_list);
5264   silc_buffer_free(client_mode_list);
5265   silc_free(id);
5266
5267  out:
5268   silc_server_command_free(cmd);
5269 }
5270
5271 /* Server side of command GETKEY. This fetches the client's public key
5272    from the server where to the client is connected. */
5273
5274 SILC_SERVER_CMD_FUNC(getkey)
5275 {
5276   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5277   SilcServer server = cmd->server;
5278   SilcBuffer packet;
5279   SilcClientEntry client;
5280   SilcServerEntry server_entry;
5281   SilcClientID *client_id = NULL;
5282   SilcServerID *server_id = NULL;
5283   SilcIDPayload idp = NULL;
5284   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5285   unsigned char *tmp, *pkdata;
5286   SilcUInt32 tmp_len, pklen;
5287   SilcBuffer pk = NULL;
5288   SilcIdType id_type;
5289   SilcPublicKey public_key;
5290
5291   SILC_LOG_DEBUG(("Start"));
5292
5293   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5294   if (!tmp) {
5295     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5296                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5297     goto out;
5298   }
5299   idp = silc_id_payload_parse(tmp, tmp_len);
5300   if (!idp) {
5301     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5302                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5303     goto out;
5304   }
5305
5306   id_type = silc_id_payload_get_type(idp);
5307   if (id_type == SILC_ID_CLIENT) {
5308     client_id = silc_id_payload_get_id(idp);
5309
5310     /* If the client is not found from local list there is no chance it
5311        would be locally connected client so send the command further. */
5312     client = silc_idlist_find_client_by_id(server->local_list, 
5313                                            client_id, TRUE, NULL);
5314     if (!client)
5315       client = silc_idlist_find_client_by_id(server->global_list, 
5316                                              client_id, TRUE, NULL);
5317     
5318     if ((!client && !cmd->pending && !server->standalone) ||
5319         (client && !client->connection && !cmd->pending) ||
5320         (client && !client->data.public_key && !cmd->pending)) {
5321       SilcBuffer tmpbuf;
5322       SilcUInt16 old_ident;
5323       SilcSocketConnection dest_sock;
5324       
5325       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5326                                                client_id, NULL);
5327       if (!dest_sock)
5328         goto out;
5329       
5330       old_ident = silc_command_get_ident(cmd->payload);
5331       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5332       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5333       
5334       silc_server_packet_send(server, dest_sock,
5335                               SILC_PACKET_COMMAND, cmd->packet->flags,
5336                               tmpbuf->data, tmpbuf->len, TRUE);
5337       
5338       /* Reprocess this packet after received reply from router */
5339       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5340                                   silc_command_get_ident(cmd->payload),
5341                                   silc_server_command_getkey,
5342                                   silc_server_command_dup(cmd));
5343       cmd->pending = TRUE;
5344       silc_command_set_ident(cmd->payload, old_ident);
5345       silc_buffer_free(tmpbuf);
5346       goto out;
5347     }
5348
5349     if (!client) {
5350       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5351                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5352       goto out;
5353     }
5354
5355     /* The client is locally connected, just get the public key and
5356        send it back. If they key does not exist then do not send it, 
5357        send just OK reply */
5358     public_key = client->data.public_key;
5359     if (!public_key) {
5360       pkdata = NULL;
5361       pklen = 0;
5362     } else {
5363       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5364       pk = silc_buffer_alloc(4 + tmp_len);
5365       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5366       silc_buffer_format(pk,
5367                          SILC_STR_UI_SHORT(tmp_len),
5368                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5369                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5370                          SILC_STR_END);
5371       silc_free(tmp);
5372       pkdata = pk->data;
5373       pklen = pk->len;
5374     }
5375   } else if (id_type == SILC_ID_SERVER) {
5376     server_id = silc_id_payload_get_id(idp);
5377
5378     /* If the server is not found from local list there is no chance it
5379        would be locally connected server so send the command further. */
5380     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5381                                                  server_id, TRUE, NULL);
5382     if (!server_entry)
5383       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5384                                                    server_id, TRUE, NULL);
5385     
5386     if (server_entry != server->id_entry &&
5387         ((!server_entry && !cmd->pending && !server->standalone) ||
5388          (server_entry && !server_entry->connection && !cmd->pending &&
5389           !server->standalone) ||
5390          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5391           !server->standalone))) {
5392       SilcBuffer tmpbuf;
5393       SilcUInt16 old_ident;
5394       
5395       old_ident = silc_command_get_ident(cmd->payload);
5396       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5397       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5398       
5399       silc_server_packet_send(server, server->router->connection,
5400                               SILC_PACKET_COMMAND, cmd->packet->flags,
5401                               tmpbuf->data, tmpbuf->len, TRUE);
5402       
5403       /* Reprocess this packet after received reply from router */
5404       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5405                                   silc_command_get_ident(cmd->payload),
5406                                   silc_server_command_getkey,
5407                                   silc_server_command_dup(cmd));
5408       cmd->pending = TRUE;
5409       silc_command_set_ident(cmd->payload, old_ident);
5410       silc_buffer_free(tmpbuf);
5411       goto out;
5412     }
5413
5414     if (!server_entry) {
5415       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5416                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5417       goto out;
5418     }
5419
5420     /* If they key does not exist then do not send it, send just OK reply */
5421     public_key = (!server_entry->data.public_key ? 
5422                   (server_entry == server->id_entry ? server->public_key :
5423                    NULL) : server_entry->data.public_key);
5424     if (!public_key) {
5425       pkdata = NULL;
5426       pklen = 0;
5427     } else {
5428       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5429       pk = silc_buffer_alloc(4 + tmp_len);
5430       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5431       silc_buffer_format(pk,
5432                          SILC_STR_UI_SHORT(tmp_len),
5433                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5434                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5435                          SILC_STR_END);
5436       silc_free(tmp);
5437       pkdata = pk->data;
5438       pklen = pk->len;
5439     }
5440   } else {
5441     goto out;
5442   }
5443
5444   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5445   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5446                                                 SILC_STATUS_OK, ident, 
5447                                                 pkdata ? 2 : 1,
5448                                                 2, tmp, tmp_len,
5449                                                 3, pkdata, pklen);
5450   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5451                           packet->data, packet->len, FALSE);
5452   silc_buffer_free(packet);
5453
5454   if (pk)
5455     silc_buffer_free(pk);
5456
5457  out:
5458   if (idp)
5459     silc_id_payload_free(idp);
5460   silc_free(client_id);
5461   silc_free(server_id);
5462   silc_server_command_free(cmd);
5463 }