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