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