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