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