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