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