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