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