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