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