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