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   }
1955
1956   return FALSE;
1957 }
1958
1959 /* Server side of command NICK. Sets nickname for user. Setting
1960    nickname causes generation of a new client ID for the client. The
1961    new client ID is sent to the client after changing the nickname. */
1962
1963 SILC_SERVER_CMD_FUNC(nick)
1964 {
1965   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1966   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1967   SilcServer server = cmd->server;
1968   SilcBuffer packet, nidp, oidp = NULL;
1969   SilcClientID *new_id;
1970   char *nick;
1971   uint16 ident = silc_command_get_ident(cmd->payload);
1972   int nickfail = 0;
1973
1974   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1975     goto out;
1976
1977   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1978
1979   /* Check nickname */
1980   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1981   if (silc_server_command_bad_chars(nick) == TRUE) {
1982     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1983                                           SILC_STATUS_ERR_BAD_NICKNAME);
1984     goto out;
1985   }
1986
1987   if (strlen(nick) > 128)
1988     nick[128] = '\0';
1989
1990   /* Check for same nickname */
1991   if (!strcmp(client->nickname, nick)) {
1992     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1993     goto send_reply;
1994   }
1995
1996   /* Create new Client ID */
1997   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
1998                                    cmd->server->rng, 
1999                                    cmd->server->md5hash, nick,
2000                                    &new_id)) {
2001     nickfail++;
2002     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2003   }
2004
2005   /* Send notify about nickname change to our router. We send the new
2006      ID and ask to replace it with the old one. If we are router the
2007      packet is broadcasted. Send NICK_CHANGE notify. */
2008   if (!server->standalone)
2009     silc_server_send_notify_nick_change(server, server->router->connection, 
2010                                         server->server_type == SILC_SERVER ? 
2011                                         FALSE : TRUE, client->id,
2012                                         new_id);
2013
2014   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2015
2016   /* Remove old cache entry */
2017   silc_idcache_del_by_context(server->local_list->clients, client);
2018
2019   /* Free old ID */
2020   silc_free(client->id);
2021
2022   /* Save the nickname as this client is our local client */
2023   silc_free(client->nickname);
2024
2025   client->nickname = strdup(nick);
2026   client->id = new_id;
2027
2028   /* Update client cache */
2029   silc_idcache_add(server->local_list->clients, client->nickname, 
2030                    client->id, (void *)client, FALSE);
2031
2032   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2033
2034   /* Send NICK_CHANGE notify to the client's channels */
2035   silc_server_send_notify_on_channels(server, NULL, client, 
2036                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2037                                       oidp->data, oidp->len, 
2038                                       nidp->data, nidp->len);
2039
2040  send_reply:
2041   /* Send the new Client ID as reply command back to client */
2042   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2043                                                 SILC_STATUS_OK, ident, 1, 
2044                                                 2, nidp->data, nidp->len);
2045   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2046                           0, packet->data, packet->len, FALSE);
2047
2048   silc_buffer_free(packet);
2049   silc_buffer_free(nidp);
2050   if (oidp)
2051     silc_buffer_free(oidp);
2052   
2053  out:
2054   silc_server_command_free(cmd);
2055 }
2056
2057 /* Sends the LIST command reply */
2058
2059 static void
2060 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2061                                     SilcChannelEntry *lch, 
2062                                     uint32 lch_count,
2063                                     SilcChannelEntry *gch,
2064                                     uint32 gch_count)
2065 {
2066   int i;
2067   SilcBuffer packet, idp;
2068   SilcChannelEntry entry;
2069   SilcCommandStatus status;
2070   uint16 ident = silc_command_get_ident(cmd->payload);
2071   char *topic;
2072   unsigned char usercount[4];
2073   uint32 users;
2074
2075   for (i = 0; i < lch_count; i++)
2076     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2077       lch[i] = NULL;
2078   for (i = 0; i < gch_count; i++)
2079     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2080       gch[i] = NULL;
2081
2082   status = SILC_STATUS_OK;
2083   if ((lch_count + gch_count) > 1)
2084     status = SILC_STATUS_LIST_START;
2085
2086   /* Local list */
2087   for (i = 0; i < lch_count; i++) {
2088     entry = lch[i];
2089
2090     if (!entry)
2091       continue;
2092
2093     if (i >= 1)
2094       status = SILC_STATUS_LIST_ITEM;
2095
2096     if (lch_count > 1 && i == lch_count - 1 && !gch_count)
2097       status = SILC_STATUS_LIST_END;
2098
2099     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2100
2101     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2102       topic = "*private*";
2103       memset(usercount, 0, sizeof(usercount));
2104     } else {
2105       topic = entry->topic;
2106       users = silc_hash_table_count(entry->user_list);
2107       SILC_PUT32_MSB(users, usercount);
2108     }
2109
2110     /* Send the reply */
2111     if (topic)
2112       packet = 
2113         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2114                                              status, ident, 4, 
2115                                              2, idp->data, idp->len,
2116                                              3, entry->channel_name, 
2117                                              strlen(entry->channel_name),
2118                                              4, topic, strlen(topic),
2119                                              5, usercount, 4);
2120     else
2121       packet = 
2122         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2123                                              status, ident, 3, 
2124                                              2, idp->data, idp->len,
2125                                              3, entry->channel_name, 
2126                                              strlen(entry->channel_name),
2127                                              5, usercount, 4);
2128     silc_server_packet_send(cmd->server, cmd->sock, 
2129                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2130                             packet->len, FALSE);
2131     silc_buffer_free(packet);
2132     silc_buffer_free(idp);
2133   }
2134
2135   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2136
2137   /* Global list */
2138   for (i = 0; i < gch_count; i++) {
2139     entry = gch[i];
2140
2141     if (!entry)
2142       continue;
2143
2144     if (i >= 1)
2145       status = SILC_STATUS_LIST_ITEM;
2146
2147     if (gch_count > 1 && i == lch_count - 1)
2148       status = SILC_STATUS_LIST_END;
2149
2150     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2151
2152     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2153       topic = "*private*";
2154       memset(usercount, 0, sizeof(usercount));
2155     } else {
2156       topic = entry->topic;
2157       users = silc_hash_table_count(entry->user_list);
2158       SILC_PUT32_MSB(users, usercount);
2159     }
2160
2161     /* Send the reply */
2162     if (topic)
2163       packet = 
2164         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2165                                              status, ident, 4, 
2166                                              2, idp->data, idp->len,
2167                                              3, entry->channel_name, 
2168                                              strlen(entry->channel_name),
2169                                              4, topic, strlen(topic),
2170                                              5, usercount, 4);
2171     else
2172       packet = 
2173         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2174                                              status, ident, 3, 
2175                                              2, idp->data, idp->len,
2176                                              3, entry->channel_name, 
2177                                              strlen(entry->channel_name),
2178                                              5, usercount, 4);
2179     silc_server_packet_send(cmd->server, cmd->sock, 
2180                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2181                             packet->len, FALSE);
2182     silc_buffer_free(packet);
2183     silc_buffer_free(idp);
2184   }
2185 }
2186
2187 /* Server side of LIST command. This lists the channel of the requested
2188    server. Secret channels are not listed. */
2189
2190 SILC_SERVER_CMD_FUNC(list)
2191 {
2192   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2193   SilcServer server = cmd->server;
2194   SilcChannelID *channel_id = NULL;
2195   unsigned char *tmp;
2196   uint32 tmp_len;
2197   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2198   uint32 lch_count = 0, gch_count = 0;
2199
2200   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2201
2202   /* If we are normal server, send the command to router, since we
2203      want to know all channels in the network. */
2204   if (!cmd->pending && server->server_type == SILC_SERVER && 
2205       !server->standalone) {
2206     SilcBuffer tmpbuf;
2207     uint16 old_ident;
2208     
2209     old_ident = silc_command_get_ident(cmd->payload);
2210     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2211     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2212     silc_server_packet_send(server, server->router->connection,
2213                             SILC_PACKET_COMMAND, cmd->packet->flags,
2214                             tmpbuf->data, tmpbuf->len, TRUE);
2215
2216     /* Reprocess this packet after received reply from router */
2217     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2218                                 silc_command_get_ident(cmd->payload),
2219                                 silc_server_command_destructor,
2220                                 silc_server_command_list, 
2221                                 silc_server_command_dup(cmd));
2222     cmd->pending = TRUE;
2223     silc_command_set_ident(cmd->payload, old_ident);
2224     silc_buffer_free(tmpbuf);
2225     return;
2226   }
2227
2228   /* Get Channel ID */
2229   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2230   if (tmp) {
2231     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2232     if (!channel_id) {
2233       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2234                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2235       goto out;
2236     }
2237   }
2238
2239   /* Get the channels from local list */
2240   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2241                                        &lch_count);
2242   
2243   /* Get the channels from global list */
2244   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2245                                        &gch_count);
2246
2247   /* Send the reply */
2248   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2249                                       gchannels, gch_count);
2250
2251  out:
2252   silc_server_command_free(cmd);
2253 }
2254
2255 /* Server side of TOPIC command. Sets topic for channel and/or returns
2256    current topic to client. */
2257
2258 SILC_SERVER_CMD_FUNC(topic)
2259 {
2260   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2261   SilcServer server = cmd->server;
2262   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2263   SilcChannelID *channel_id;
2264   SilcChannelEntry channel;
2265   SilcChannelClientEntry chl;
2266   SilcBuffer packet, idp;
2267   unsigned char *tmp;
2268   uint32 argc, tmp_len;
2269   uint16 ident = silc_command_get_ident(cmd->payload);
2270
2271   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2272
2273   argc = silc_argument_get_arg_num(cmd->args);
2274
2275   /* Get Channel ID */
2276   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2277   if (!tmp) {
2278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2279                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2280     goto out;
2281   }
2282   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2283   if (!channel_id) {
2284     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2285                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2286     goto out;
2287   }
2288
2289   /* Check whether the channel exists */
2290   channel = silc_idlist_find_channel_by_id(server->local_list, 
2291                                            channel_id, NULL);
2292   if (!channel) {
2293     channel = silc_idlist_find_channel_by_id(server->global_list, 
2294                                              channel_id, NULL);
2295     if (!channel) {
2296       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2297                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2298       goto out;
2299     }
2300   }
2301
2302   if (argc > 1) {
2303     /* Get the topic */
2304     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2305     if (!tmp) {
2306       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2307                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2308       goto out;
2309     }
2310
2311     if (strlen(tmp) > 256) {
2312       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2313                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2314       goto out;
2315     }
2316
2317     /* See whether the client is on channel and has rights to change topic */
2318     if (!silc_hash_table_find(channel->user_list, client, NULL, 
2319                               (void *)&chl)) {
2320       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2322       goto out;
2323     }
2324
2325     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2326       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2327         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2329         goto out;
2330       }
2331     }
2332
2333     /* Set the topic for channel */
2334     silc_free(channel->topic);
2335     channel->topic = strdup(tmp);
2336
2337     /* Send TOPIC_SET notify type to the network */
2338     if (!server->standalone)
2339       silc_server_send_notify_topic_set(server, server->router->connection,
2340                                         server->server_type == SILC_ROUTER ?
2341                                         TRUE : FALSE, channel, client->id,
2342                                         channel->topic);
2343
2344     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2345
2346     /* Send notify about topic change to all clients on the channel */
2347     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2348                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2349                                        idp->data, idp->len,
2350                                        channel->topic, strlen(channel->topic));
2351     silc_buffer_free(idp);
2352   }
2353
2354   /* Send the topic to client as reply packet */
2355   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2356   if (channel->topic)
2357     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2358                                                   SILC_STATUS_OK, ident, 2, 
2359                                                   2, idp->data, idp->len,
2360                                                   3, channel->topic, 
2361                                                   strlen(channel->topic));
2362   else
2363     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2364                                                   SILC_STATUS_OK, ident, 1, 
2365                                                   2, idp->data, idp->len);
2366   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2367                           0, packet->data, packet->len, FALSE);
2368
2369   silc_buffer_free(packet);
2370   silc_buffer_free(idp);
2371   silc_free(channel_id);
2372
2373  out:
2374   silc_server_command_free(cmd);
2375 }
2376
2377 /* Server side of INVITE command. Invites some client to join some channel. 
2378    This command is also used to manage the invite list of the channel. */
2379
2380 SILC_SERVER_CMD_FUNC(invite)
2381 {
2382   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2383   SilcServer server = cmd->server;
2384   SilcSocketConnection sock = cmd->sock, dest_sock;
2385   SilcChannelClientEntry chl;
2386   SilcClientEntry sender, dest;
2387   SilcClientID *dest_id = NULL;
2388   SilcChannelEntry channel;
2389   SilcChannelID *channel_id = NULL;
2390   SilcIDListData idata;
2391   SilcBuffer idp, idp2, packet;
2392   unsigned char *tmp, *add, *del;
2393   uint32 len;
2394   uint16 ident = silc_command_get_ident(cmd->payload);
2395
2396   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2397
2398   /* Get Channel ID */
2399   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2400   if (!tmp) {
2401     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2403     goto out;
2404   }
2405   channel_id = silc_id_payload_parse_id(tmp, len);
2406   if (!channel_id) {
2407     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2408                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2409     goto out;
2410   }
2411
2412   /* Get the channel entry */
2413   channel = silc_idlist_find_channel_by_id(server->local_list, 
2414                                            channel_id, NULL);
2415   if (!channel) {
2416     channel = silc_idlist_find_channel_by_id(server->global_list, 
2417                                              channel_id, NULL);
2418     if (!channel) {
2419       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2420                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2421       goto out;
2422     }
2423   }
2424
2425   /* Check whether the sender of this command is on the channel. */
2426   sender = (SilcClientEntry)sock->user_data;
2427   if (!silc_server_client_on_channel(sender, channel)) {
2428     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2429                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2430     goto out;
2431   }
2432
2433   /* Check whether the channel is invite-only channel. If yes then the
2434      sender of this command must be at least channel operator. */
2435   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2436     silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2437     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2438       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2440       goto out;
2441     }
2442   }
2443
2444   /* Get destination client ID */
2445   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2446   if (tmp) {
2447     char invite[512];
2448
2449     dest_id = silc_id_payload_parse_id(tmp, len);
2450     if (!dest_id) {
2451       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2452                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2453       goto out;
2454     }
2455
2456     /* Get the client entry */
2457     dest = silc_server_get_client_resolve(server, dest_id);
2458     if (!dest) {
2459       if (server->server_type != SILC_SERVER) {
2460         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2461                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2462         goto out;
2463       }
2464       
2465       /* The client info is being resolved. Reprocess this packet after
2466          receiving the reply to the query. */
2467       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2468                                   server->cmd_ident,
2469                                   silc_server_command_destructor,
2470                                   silc_server_command_invite, 
2471                                   silc_server_command_dup(cmd));
2472       cmd->pending = TRUE;
2473       silc_free(channel_id);
2474       silc_free(dest_id);
2475       return;
2476     }
2477
2478     /* Check whether the requested client is already on the channel. */
2479     if (silc_server_client_on_channel(dest, channel)) {
2480       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2481                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2482       goto out;
2483     }
2484     
2485     /* Get route to the client */
2486     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2487     if (!dest_sock) {
2488       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2489                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2490       goto out;
2491     }
2492
2493     memset(invite, 0, sizeof(invite));
2494     strncat(invite, dest->nickname, strlen(dest->nickname));
2495     strncat(invite, "!", 1);
2496     strncat(invite, dest->username, strlen(dest->username));
2497     if (!strchr(dest->username, '@')) {
2498       strncat(invite, "@", 1);
2499       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2500     }
2501
2502     len = strlen(invite);
2503     if (!channel->invite_list)
2504       channel->invite_list = silc_calloc(len + 2, 
2505                                          sizeof(*channel->invite_list));
2506     else
2507       channel->invite_list = silc_realloc(channel->invite_list, 
2508                                           sizeof(*channel->invite_list) * 
2509                                           (len + 
2510                                            strlen(channel->invite_list) + 2));
2511     strncat(channel->invite_list, invite, len);
2512     strncat(channel->invite_list, ",", 1);
2513
2514     /* Send notify to the client that is invited to the channel */
2515     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2516     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2517     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2518                                  SILC_ID_CLIENT,
2519                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2520                                  idp->data, idp->len, 
2521                                  channel->channel_name, 
2522                                  strlen(channel->channel_name),
2523                                  idp2->data, idp2->len);
2524     silc_buffer_free(idp);
2525     silc_buffer_free(idp2);
2526   }
2527
2528   /* Add the client to the invite list of the channel */
2529   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2530   if (add) {
2531     if (!channel->invite_list)
2532       channel->invite_list = silc_calloc(len + 2, 
2533                                          sizeof(*channel->invite_list));
2534     else
2535       channel->invite_list = silc_realloc(channel->invite_list, 
2536                                           sizeof(*channel->invite_list) * 
2537                                           (len + 
2538                                            strlen(channel->invite_list) + 2));
2539     if (add[len - 1] == ',')
2540       add[len - 1] = '\0';
2541     
2542     strncat(channel->invite_list, add, len);
2543     strncat(channel->invite_list, ",", 1);
2544   }
2545
2546   /* Get the invite to be removed and remove it from the list */
2547   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2548   if (del && channel->invite_list) {
2549     char *start, *end, *n;
2550
2551     if (!strncmp(channel->invite_list, del, 
2552                  strlen(channel->invite_list) - 1)) {
2553       silc_free(channel->invite_list);
2554       channel->invite_list = NULL;
2555     } else {
2556       start = strstr(channel->invite_list, del);
2557       if (start && strlen(start) >= len) {
2558         end = start + len;
2559         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2560         strncat(n, channel->invite_list, start - channel->invite_list);
2561         strncat(n, end + 1, ((channel->invite_list + 
2562                               strlen(channel->invite_list)) - end) - 1);
2563         silc_free(channel->invite_list);
2564         channel->invite_list = n;
2565       }
2566     }
2567   }
2568
2569   /* Send notify to the primary router */
2570   if (!server->standalone)
2571     silc_server_send_notify_invite(server, server->router->connection,
2572                                    server->server_type == SILC_ROUTER ?
2573                                    TRUE : FALSE, channel,
2574                                    sender->id, add, del);
2575
2576   /* Send command reply */
2577   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2578
2579   if (add || del)
2580     packet = 
2581       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2582                                            SILC_STATUS_OK, ident, 2,
2583                                            2, tmp, len,
2584                                            3, channel->invite_list,
2585                                            channel->invite_list ?
2586                                            strlen(channel->invite_list) : 0);
2587   else
2588     packet = 
2589       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2590                                            SILC_STATUS_OK, ident, 1,
2591                                            2, tmp, len);
2592   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2593                           packet->data, packet->len, FALSE);
2594   silc_buffer_free(packet);
2595
2596  out:
2597   silc_free(dest_id);
2598   silc_free(channel_id);
2599   silc_server_command_free(cmd);
2600 }
2601
2602 typedef struct {
2603   SilcServer server;
2604   SilcSocketConnection sock;
2605   char *signoff;
2606 } *QuitInternal;
2607
2608 /* Quits connection to client. This gets called if client won't
2609    close the connection even when it has issued QUIT command. */
2610
2611 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2612 {
2613   QuitInternal q = (QuitInternal)context;
2614
2615   /* Free all client specific data, such as client entry and entires
2616      on channels this client may be on. */
2617   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2618                                TRUE, q->signoff);
2619   q->sock->user_data = NULL;
2620
2621   /* Close the connection on our side */
2622   silc_server_close_connection(q->server, q->sock);
2623
2624   silc_free(q->signoff);
2625   silc_free(q);
2626 }
2627
2628 /* Quits SILC session. This is the normal way to disconnect client. */
2629  
2630 SILC_SERVER_CMD_FUNC(quit)
2631 {
2632   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2633   SilcServer server = cmd->server;
2634   SilcSocketConnection sock = cmd->sock;
2635   QuitInternal q;
2636   unsigned char *tmp = NULL;
2637   uint32 len = 0;
2638
2639   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2640
2641   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2642     goto out;
2643
2644   /* Get destination ID */
2645   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2646   if (len > 128)
2647     tmp = NULL;
2648
2649   q = silc_calloc(1, sizeof(*q));
2650   q->server = server;
2651   q->sock = sock;
2652   q->signoff = tmp ? strdup(tmp) : NULL;
2653
2654   /* We quit the connection with little timeout */
2655   silc_schedule_task_add(server->schedule, sock->sock,
2656                      silc_server_command_quit_cb, (void *)q,
2657                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2658
2659  out:
2660   silc_server_command_free(cmd);
2661 }
2662
2663 /* Server side of command KILL. This command is used by router operator
2664    to remove an client from the SILC Network temporarily. */
2665
2666 SILC_SERVER_CMD_FUNC(kill)
2667 {
2668   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2669   SilcServer server = cmd->server;
2670   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2671   SilcClientEntry remote_client;
2672   SilcClientID *client_id;
2673   unsigned char *tmp, *comment;
2674   uint32 tmp_len, tmp_len2;
2675
2676   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2677
2678   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2679     goto out;
2680
2681   /* KILL command works only on router */
2682   if (server->server_type != SILC_ROUTER) {
2683     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2685     goto out;
2686   }
2687
2688   /* Check whether client has the permissions. */
2689   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2690     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692     goto out;
2693   }
2694
2695   /* Get the client ID */
2696   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2697   if (!tmp) {
2698     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2699                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2700     goto out;
2701   }
2702   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2703   if (!client_id) {
2704     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2706     goto out;
2707   }
2708
2709   /* Get the client entry */
2710   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2711                                                 client_id, TRUE, NULL);
2712   if (!remote_client) {
2713     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2714                                                   client_id, TRUE, NULL);
2715     if (!remote_client) {
2716       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2717                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2718       goto out;
2719     }
2720   }
2721
2722   /* Get comment */
2723   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2724   if (tmp_len2 > 128)
2725     comment = NULL;
2726
2727   /* Send reply to the sender */
2728   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2729                                         SILC_STATUS_OK);
2730
2731   /* Send the KILL notify packets. First send it to the channel, then
2732      to our primary router and then directly to the client who is being
2733      killed right now. */
2734
2735   /* Send KILLED notify to the channels. It is not sent to the client
2736      as it will be sent differently destined directly to the client and not
2737      to the channel. */
2738   silc_server_send_notify_on_channels(server, remote_client, 
2739                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2740                                       comment ? 2 : 1,
2741                                       tmp, tmp_len,
2742                                       comment, comment ? tmp_len2 : 0);
2743
2744   /* Send KILLED notify to primary route */
2745   if (!server->standalone)
2746     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2747                                    remote_client->id, comment);
2748
2749   /* Send KILLED notify to the client directly */
2750   silc_server_send_notify_killed(server, remote_client->connection ? 
2751                                  remote_client->connection : 
2752                                  remote_client->router->connection, FALSE,
2753                                  remote_client->id, comment);
2754
2755   /* Remove the client from all channels. This generates new keys to the
2756      channels as well. */
2757   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2758                                    NULL, TRUE);
2759
2760   /* Remove the client entry, If it is locally connected then we will also
2761      disconnect the client here */
2762   if (remote_client->connection) {
2763     /* Remove locally conneted client */
2764     SilcSocketConnection sock = remote_client->connection;
2765     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2766     silc_server_close_connection(server, sock);
2767   } else {
2768     /* Remove remote client */
2769     if (!silc_idlist_del_client(server->global_list, remote_client))
2770       silc_idlist_del_client(server->local_list, remote_client);
2771   }
2772
2773  out:
2774   silc_server_command_free(cmd);
2775 }
2776
2777 /* Server side of command INFO. This sends information about us to 
2778    the client. If client requested specific server we will send the 
2779    command to that server. */
2780
2781 SILC_SERVER_CMD_FUNC(info)
2782 {
2783   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2784   SilcServer server = cmd->server;
2785   SilcBuffer packet, idp;
2786   unsigned char *tmp;
2787   uint32 tmp_len;
2788   char *dest_server, *server_info = NULL, *server_name;
2789   uint16 ident = silc_command_get_ident(cmd->payload);
2790   SilcServerEntry entry = NULL;
2791   SilcServerID *server_id = NULL;
2792
2793   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2794
2795   /* Get server name */
2796   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2797
2798   /* Get Server ID */
2799   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2800   if (tmp) {
2801     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2802     if (!server_id) {
2803       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2804                                             SILC_STATUS_ERR_NO_SERVER_ID);
2805       goto out;
2806     }
2807   }
2808
2809   if (server_id) {
2810     /* Check whether we have this server cached */
2811     entry = silc_idlist_find_server_by_id(server->local_list,
2812                                           server_id, TRUE, NULL);
2813     if (!entry) {
2814       entry = silc_idlist_find_server_by_id(server->global_list,
2815                                             server_id, TRUE, NULL);
2816       if (!entry && server->server_type != SILC_SERVER) {
2817         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2818                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2819         goto out;
2820       }
2821     }
2822   }
2823
2824   /* Some buggy servers has sent request to router about themselves. */
2825   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2826     goto out;
2827
2828   if ((!dest_server && !server_id && !entry) || (entry && 
2829                                                  entry == server->id_entry) ||
2830       (dest_server && !cmd->pending && 
2831        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2832     /* Send our reply */
2833     char info_string[256];
2834
2835     memset(info_string, 0, sizeof(info_string));
2836     snprintf(info_string, sizeof(info_string), 
2837              "location: %s server: %s admin: %s <%s>",
2838              server->config->admin_info->location,
2839              server->config->admin_info->server_type,
2840              server->config->admin_info->admin_name,
2841              server->config->admin_info->admin_email);
2842
2843     server_info = info_string;
2844     entry = server->id_entry;
2845   } else {
2846     /* Check whether we have this server cached */
2847     if (!entry && dest_server) {
2848       entry = silc_idlist_find_server_by_name(server->global_list,
2849                                               dest_server, TRUE, NULL);
2850       if (!entry) {
2851         entry = silc_idlist_find_server_by_name(server->local_list,
2852                                                 dest_server, TRUE, NULL);
2853       }
2854     }
2855
2856     if (!cmd->pending &&
2857         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2858       /* Send to the server */
2859       SilcBuffer tmpbuf;
2860       uint16 old_ident;
2861
2862       old_ident = silc_command_get_ident(cmd->payload);
2863       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2864       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2865
2866       silc_server_packet_send(server, entry->connection,
2867                               SILC_PACKET_COMMAND, cmd->packet->flags,
2868                               tmpbuf->data, tmpbuf->len, TRUE);
2869
2870       /* Reprocess this packet after received reply from router */
2871       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2872                                   silc_command_get_ident(cmd->payload),
2873                                   silc_server_command_destructor,
2874                                   silc_server_command_info,
2875                                   silc_server_command_dup(cmd));
2876       cmd->pending = TRUE;
2877       silc_command_set_ident(cmd->payload, old_ident);
2878       silc_buffer_free(tmpbuf);
2879       return;
2880     }
2881
2882     if (!entry && !cmd->pending && !server->standalone) {
2883       /* Send to the primary router */
2884       SilcBuffer tmpbuf;
2885       uint16 old_ident;
2886
2887       old_ident = silc_command_get_ident(cmd->payload);
2888       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2889       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2890
2891       silc_server_packet_send(server, server->router->connection,
2892                               SILC_PACKET_COMMAND, cmd->packet->flags,
2893                               tmpbuf->data, tmpbuf->len, TRUE);
2894
2895       /* Reprocess this packet after received reply from router */
2896       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2897                                   silc_command_get_ident(cmd->payload),
2898                                   silc_server_command_destructor,
2899                                   silc_server_command_info,
2900                                   silc_server_command_dup(cmd));
2901       cmd->pending = TRUE;
2902       silc_command_set_ident(cmd->payload, old_ident);
2903       silc_buffer_free(tmpbuf);
2904       return;
2905     }
2906   }
2907
2908   silc_free(server_id);
2909
2910   if (!entry) {
2911     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2912                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2913     goto out;
2914   }
2915
2916   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2917   if (!server_info)
2918     server_info = entry->server_info;
2919   server_name = entry->server_name;
2920
2921   /* Send the reply */
2922   if (server_info)
2923     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2924                                                   SILC_STATUS_OK, ident, 3,
2925                                                   2, idp->data, idp->len,
2926                                                   3, server_name, 
2927                                                   strlen(server_name),
2928                                                   4, server_info, 
2929                                                   strlen(server_info));
2930   else
2931     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2932                                                   SILC_STATUS_OK, ident, 2,
2933                                                   2, idp->data, idp->len,
2934                                                   3, server_name, 
2935                                                   strlen(server_name));
2936   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2937                           packet->data, packet->len, FALSE);
2938     
2939   silc_buffer_free(packet);
2940   silc_buffer_free(idp);
2941
2942  out:
2943   silc_server_command_free(cmd);
2944 }
2945
2946 /* Server side of command PING. This just replies to the ping. */
2947
2948 SILC_SERVER_CMD_FUNC(ping)
2949 {
2950   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2951   SilcServer server = cmd->server;
2952   SilcServerID *id;
2953   uint32 len;
2954   unsigned char *tmp;
2955
2956   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2957
2958   /* Get Server ID */
2959   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2960   if (!tmp) {
2961     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2962                                           SILC_STATUS_ERR_NO_SERVER_ID);
2963     goto out;
2964   }
2965   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2966   if (!id)
2967     goto out;
2968
2969   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2970     /* Send our reply */
2971     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2972                                           SILC_STATUS_OK);
2973   } else {
2974     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2975                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2976     goto out;
2977   }
2978
2979   silc_free(id);
2980
2981  out:
2982   silc_server_command_free(cmd);
2983 }
2984
2985 /* Internal routine to join channel. The channel sent to this function
2986    has been either created or resolved from ID lists. This joins the sent
2987    client to the channel. */
2988
2989 static void silc_server_command_join_channel(SilcServer server, 
2990                                              SilcServerCommandContext cmd,
2991                                              SilcChannelEntry channel,
2992                                              SilcClientID *client_id,
2993                                              bool created,
2994                                              bool create_key,
2995                                              uint32 umode)
2996 {
2997   SilcSocketConnection sock = cmd->sock;
2998   unsigned char *tmp;
2999   uint32 tmp_len, user_count;
3000   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3001   SilcClientEntry client;
3002   SilcChannelClientEntry chl;
3003   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3004   uint16 ident = silc_command_get_ident(cmd->payload);
3005   char check[512], check2[512];
3006
3007   SILC_LOG_DEBUG(("Start"));
3008
3009   if (!channel)
3010     return;
3011
3012   /* Get the client entry */
3013   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3014     client = (SilcClientEntry)sock->user_data;
3015   } else {
3016     client = silc_server_get_client_resolve(server, client_id);
3017     if (!client) {
3018       if (cmd->pending)
3019         goto out;
3020
3021       /* The client info is being resolved. Reprocess this packet after
3022          receiving the reply to the query. */
3023       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3024                                   server->cmd_ident, NULL,
3025                                   silc_server_command_join, 
3026                                   silc_server_command_dup(cmd));
3027       cmd->pending = TRUE;
3028       return;
3029     }
3030
3031     cmd->pending = FALSE;
3032   }
3033
3034   /*
3035    * Check channel modes
3036    */
3037
3038   memset(check, 0, sizeof(check));
3039   memset(check2, 0, sizeof(check2));
3040   strncat(check, client->nickname, strlen(client->nickname));
3041   strncat(check, "!", 1);
3042   strncat(check, client->username, strlen(client->username));
3043   if (!strchr(client->username, '@')) {
3044     strncat(check, "@", 1);
3045     strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3046   }
3047
3048   strncat(check2, client->nickname, strlen(client->nickname));
3049   if (!strchr(client->nickname, '@')) {
3050     strncat(check2, "@", 1);
3051     strncat(check2, server->server_name, strlen(server->server_name));
3052   }
3053   strncat(check2, "!", 1);
3054   strncat(check2, client->username, strlen(client->username));
3055   if (!strchr(client->username, '@')) {
3056     strncat(check2, "@", 1);
3057     strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3058   }
3059
3060   /* Check invite list if channel is invite-only channel */
3061   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3062     if (!channel->invite_list ||
3063         (!silc_string_match(channel->invite_list, check) &&
3064          !silc_string_match(channel->invite_list, check2))) {
3065       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3066                                             SILC_STATUS_ERR_NOT_INVITED);
3067       goto out;
3068     }
3069   }
3070
3071   /* Check ban list if it exists. If the client's nickname, server,
3072      username and/or hostname is in the ban list the access to the
3073      channel is denied. */
3074   if (channel->ban_list) {
3075     if (!channel->ban_list ||
3076         silc_string_match(channel->ban_list, check) ||
3077         silc_string_match(channel->ban_list, check2)) {
3078       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3079                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3080       goto out;
3081     }
3082   }
3083
3084   /* Get passphrase */
3085   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3086   if (tmp) {
3087     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3088     memcpy(passphrase, tmp, tmp_len);
3089   }
3090   
3091   /* Check the channel passphrase if set. */
3092   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3093     if (!passphrase || !channel->passphrase ||
3094         memcmp(channel->passphrase, passphrase,
3095                strlen(channel->passphrase))) {
3096       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3097                                             SILC_STATUS_ERR_BAD_PASSWORD);
3098       goto out;
3099     }
3100   }
3101
3102   /* Check user count limit if set. */
3103   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3104     if (silc_hash_table_count(channel->user_list) + 1 > 
3105         channel->user_limit) {
3106       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3107                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
3108       goto out;
3109     }
3110   }
3111
3112   /*
3113    * Client is allowed to join to the channel. Make it happen.
3114    */
3115
3116   /* Check whether the client already is on the channel */
3117   if (silc_server_client_on_channel(client, channel)) {
3118     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3119                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3120     goto out;
3121   }
3122
3123   /* Generate new channel key as protocol dictates */
3124   if (create_key) {
3125     if (!silc_server_create_channel_key(server, channel, 0))
3126       goto out;
3127
3128     /* Send the channel key. This is broadcasted to the channel but is not
3129        sent to the client who is joining to the channel. */
3130     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3131       silc_server_send_channel_key(server, NULL, channel, 
3132                                    server->server_type == SILC_ROUTER ? 
3133                                    FALSE : !server->standalone);
3134   }
3135
3136   /* Join the client to the channel by adding it to channel's user list.
3137      Add also the channel to client entry's channels list for fast cross-
3138      referencing. */
3139   chl = silc_calloc(1, sizeof(*chl));
3140   chl->mode = umode;
3141   chl->client = client;
3142   chl->channel = channel;
3143   silc_hash_table_add(channel->user_list, client, chl);
3144   silc_hash_table_add(client->channels, channel, chl);
3145
3146   /* Get users on the channel */
3147   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3148                                    &user_count);
3149
3150   /* Encode Client ID Payload of the original client who wants to join */
3151   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3152
3153   /* Encode command reply packet */
3154   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3155   SILC_PUT32_MSB(channel->mode, mode);
3156   SILC_PUT32_MSB(created, tmp2);
3157   SILC_PUT32_MSB(user_count, tmp3);
3158
3159   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3160     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3161     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3162                                            strlen(channel->channel_key->
3163                                                   cipher->name),
3164                                            channel->channel_key->cipher->name,
3165                                            channel->key_len / 8, channel->key);
3166     silc_free(tmp);
3167   }
3168
3169   reply = 
3170     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3171                                          SILC_STATUS_OK, ident, 13,
3172                                          2, channel->channel_name,
3173                                          strlen(channel->channel_name),
3174                                          3, chidp->data, chidp->len,
3175                                          4, clidp->data, clidp->len,
3176                                          5, mode, 4,
3177                                          6, tmp2, 4,
3178                                          7, keyp ? keyp->data : NULL, 
3179                                          keyp ? keyp->len : 0,
3180                                          8, channel->ban_list, 
3181                                          channel->ban_list ?
3182                                          strlen(channel->ban_list) : 0,
3183                                          9, channel->invite_list,
3184                                          channel->invite_list ?
3185                                          strlen(channel->invite_list) : 0,
3186                                          10, channel->topic,
3187                                          channel->topic ?
3188                                          strlen(channel->topic) : 0,
3189                                          11, silc_hmac_get_name(channel->hmac),
3190                                          strlen(silc_hmac_get_name(channel->
3191                                                                    hmac)),
3192                                          12, tmp3, 4,
3193                                          13, user_list->data, user_list->len,
3194                                          14, mode_list->data, 
3195                                          mode_list->len);
3196
3197   /* Send command reply */
3198   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3199                           reply->data, reply->len, FALSE);
3200
3201   /* Send JOIN notify to locally connected clients on the channel. If
3202      we are normal server then router will send or have sent JOIN notify
3203      already. However since we've added the client already to our channel
3204      we'll ignore it (in packet_receive.c) so we must send it here. If
3205      we are router then this will send it to local clients and local
3206      servers. */
3207   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3208                                      SILC_NOTIFY_TYPE_JOIN, 2,
3209                                      clidp->data, clidp->len,
3210                                      chidp->data, chidp->len);
3211
3212   if (!cmd->pending) {
3213     /* Send JOIN notify packet to our primary router */
3214     if (!server->standalone)
3215       silc_server_send_notify_join(server, server->router->connection,
3216                                    server->server_type == SILC_ROUTER ?
3217                                    TRUE : FALSE, channel, client->id);
3218
3219     if (keyp)
3220       /* Distribute the channel key to all backup routers. */
3221       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3222                               keyp->data, keyp->len, FALSE, TRUE);
3223   }
3224
3225   silc_buffer_free(reply);
3226   silc_buffer_free(clidp);
3227   silc_buffer_free(chidp);
3228   silc_buffer_free(keyp);
3229   silc_buffer_free(user_list);
3230   silc_buffer_free(mode_list);
3231
3232  out:
3233   silc_free(passphrase);
3234 }
3235
3236 /* Server side of command JOIN. Joins client into requested channel. If 
3237    the channel does not exist it will be created. */
3238
3239 SILC_SERVER_CMD_FUNC(join)
3240 {
3241   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3242   SilcServer server = cmd->server;
3243   uint32 tmp_len;
3244   char *tmp, *channel_name = NULL, *cipher, *hmac;
3245   SilcChannelEntry channel;
3246   uint32 umode = 0;
3247   bool created = FALSE, create_key = TRUE;
3248   SilcClientID *client_id;
3249
3250   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3251
3252   /* Get channel name */
3253   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3254   if (!tmp) {
3255     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3257     goto out;
3258   }
3259   channel_name = tmp;
3260
3261   if (strlen(channel_name) > 256)
3262     channel_name[255] = '\0';
3263
3264   if (silc_server_command_bad_chars(channel_name) == TRUE) {
3265     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3266                                           SILC_STATUS_ERR_BAD_CHANNEL);
3267     goto out;
3268   }
3269
3270   /* Get Client ID of the client who is joining to the channel */
3271   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3272   if (!tmp) {
3273     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3274                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3275     goto out;
3276   }
3277   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3278   if (!client_id) {
3279     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3280                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3281     goto out;
3282   }
3283
3284   /* Get cipher and hmac name */
3285   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3286   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3287
3288   /* See if the channel exists */
3289   channel = silc_idlist_find_channel_by_name(server->local_list, 
3290                                              channel_name, NULL);
3291
3292   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3293     /* If this is coming from client the Client ID in the command packet must
3294        be same as the client's ID. */
3295     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3296       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3297       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3298         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3299                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3300         goto out;
3301       }
3302     }
3303
3304     if (!channel || channel->disabled) {
3305       /* Channel not found */
3306
3307       /* If we are standalone server we don't have a router, we just create 
3308          the channel by ourselves. */
3309       if (server->standalone) {
3310         channel = silc_server_create_new_channel(server, server->id, cipher, 
3311                                                  hmac, channel_name, TRUE);
3312         if (!channel) {
3313           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3315           goto out;
3316         }
3317         
3318         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3319         created = TRUE;
3320         create_key = FALSE;
3321         
3322       } else {
3323
3324         /* The channel does not exist on our server. If we are normal server 
3325            we will send JOIN command to our router which will handle the
3326            joining procedure (either creates the channel if it doesn't exist 
3327            or joins the client to it). */
3328         if (server->server_type != SILC_ROUTER) {
3329           SilcBuffer tmpbuf;
3330           uint16 old_ident;
3331
3332           /* If this is pending command callback then we've resolved
3333              it and it didn't work, return since we've notified the
3334              client already in the command reply callback. */
3335           if (cmd->pending)
3336             goto out;
3337           
3338           old_ident = silc_command_get_ident(cmd->payload);
3339           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3340           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3341           
3342           /* Send JOIN command to our router */
3343           silc_server_packet_send(server, (SilcSocketConnection)
3344                                   server->router->connection,
3345                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3346                                   tmpbuf->data, tmpbuf->len, TRUE);
3347           
3348           /* Reprocess this packet after received reply from router */
3349           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3350                                       silc_command_get_ident(cmd->payload),
3351                                       silc_server_command_destructor,
3352                                       silc_server_command_join,
3353                                       silc_server_command_dup(cmd));
3354           cmd->pending = TRUE;
3355           return;
3356         }
3357         
3358         /* We are router and the channel does not seem exist so we will check
3359            our global list as well for the channel. */
3360         channel = silc_idlist_find_channel_by_name(server->global_list, 
3361                                                    channel_name, NULL);
3362         if (!channel) {
3363           /* Channel really does not exist, create it */
3364           channel = silc_server_create_new_channel(server, server->id, cipher, 
3365                                                    hmac, channel_name, TRUE);
3366           if (!channel) {
3367             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3368                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3369             goto out;
3370           }
3371
3372           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3373           created = TRUE;
3374           create_key = FALSE;
3375         }
3376       }
3377     }
3378   } else {
3379     if (!channel) {
3380       /* Channel not found */
3381
3382       /* If the command came from router and we are normal server then
3383          something went wrong with the joining as the channel was not found.
3384          We can't do anything else but ignore this. */
3385       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3386           server->server_type != SILC_ROUTER)
3387         goto out;
3388       
3389       /* We are router and the channel does not seem exist so we will check
3390          our global list as well for the channel. */
3391       channel = silc_idlist_find_channel_by_name(server->global_list, 
3392                                                  channel_name, NULL);
3393       if (!channel) {
3394         /* Channel really does not exist, create it */
3395         channel = silc_server_create_new_channel(server, server->id, cipher, 
3396                                                  hmac, channel_name, TRUE);
3397         if (!channel) {
3398           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3399                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3400           goto out;
3401         }
3402
3403         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3404         created = TRUE;
3405         create_key = FALSE;
3406       }
3407     }
3408   }
3409
3410   /* Check whether the channel was created by our router */
3411   if (cmd->pending && context2) {
3412     SilcServerCommandReplyContext reply = 
3413       (SilcServerCommandReplyContext)context2;
3414     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3415       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3416       SILC_GET32_MSB(created, tmp);
3417       create_key = FALSE;       /* Router returned the key already */
3418     }
3419   }
3420
3421   /* If the channel does not have global users and is also empty the client
3422      will be the channel founder and operator. */
3423   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3424     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3425
3426   /* Join to the channel */
3427   silc_server_command_join_channel(server, cmd, channel, client_id,
3428                                    created, create_key, umode);
3429
3430   silc_free(client_id);
3431
3432  out:
3433   silc_server_command_free(cmd);
3434 }
3435
3436 /* Server side of command MOTD. Sends server's current "message of the
3437    day" to the client. */
3438
3439 SILC_SERVER_CMD_FUNC(motd)
3440 {
3441   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3442   SilcServer server = cmd->server;
3443   SilcBuffer packet, idp;
3444   char *motd, *dest_server;
3445   uint32 motd_len;
3446   uint16 ident = silc_command_get_ident(cmd->payload);
3447   
3448   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3449
3450   /* Get server name */
3451   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3452   if (!dest_server) {
3453     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3454                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3455     goto out;
3456   }
3457
3458   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3459     /* Send our MOTD */
3460
3461     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3462
3463     if (server->config && server->config->motd && 
3464         server->config->motd->motd_file) {
3465       /* Send motd */
3466       motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3467       if (!motd)
3468         goto out;
3469       
3470       motd[motd_len] = 0;
3471       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3472                                                     SILC_STATUS_OK, ident, 2,
3473                                                     2, idp, idp->len,
3474                                                     3, motd, motd_len);
3475       goto out;
3476     } else {
3477       /* No motd */
3478       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3479                                                     SILC_STATUS_OK, ident, 1,
3480                                                     2, idp, idp->len);
3481     }
3482
3483     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3484                             packet->data, packet->len, FALSE);
3485     silc_buffer_free(packet);
3486     silc_buffer_free(idp);
3487   } else {
3488     SilcServerEntry entry;
3489
3490     /* Check whether we have this server cached */
3491     entry = silc_idlist_find_server_by_name(server->global_list,
3492                                             dest_server, TRUE, NULL);
3493     if (!entry) {
3494       entry = silc_idlist_find_server_by_name(server->local_list,
3495                                               dest_server, TRUE, NULL);
3496     }
3497
3498     if (server->server_type != SILC_SERVER && !cmd->pending && 
3499         entry && !entry->motd) {
3500       /* Send to the server */
3501       SilcBuffer tmpbuf;
3502       uint16 old_ident;
3503
3504       old_ident = silc_command_get_ident(cmd->payload);
3505       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3506       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3507
3508       silc_server_packet_send(server, entry->connection,
3509                               SILC_PACKET_COMMAND, cmd->packet->flags,
3510                               tmpbuf->data, tmpbuf->len, TRUE);
3511
3512       /* Reprocess this packet after received reply from router */
3513       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3514                                   silc_command_get_ident(cmd->payload),
3515                                   silc_server_command_destructor,
3516                                   silc_server_command_motd,
3517                                   silc_server_command_dup(cmd));
3518       cmd->pending = TRUE;
3519       silc_command_set_ident(cmd->payload, old_ident);
3520       silc_buffer_free(tmpbuf);
3521       return;
3522     }
3523
3524     if (!entry && !cmd->pending && !server->standalone) {
3525       /* Send to the primary router */
3526       SilcBuffer tmpbuf;
3527       uint16 old_ident;
3528
3529       old_ident = silc_command_get_ident(cmd->payload);
3530       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3531       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3532
3533       silc_server_packet_send(server, server->router->connection,
3534                               SILC_PACKET_COMMAND, cmd->packet->flags,
3535                               tmpbuf->data, tmpbuf->len, TRUE);
3536
3537       /* Reprocess this packet after received reply from router */
3538       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3539                                   silc_command_get_ident(cmd->payload),
3540                                   silc_server_command_destructor,
3541                                   silc_server_command_motd,
3542                                   silc_server_command_dup(cmd));
3543       cmd->pending = TRUE;
3544       silc_command_set_ident(cmd->payload, old_ident);
3545       silc_buffer_free(tmpbuf);
3546       return;
3547     }
3548
3549     if (!entry) {
3550       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3551                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3552       goto out;
3553     }
3554
3555     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3556
3557     if (entry->motd)
3558       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3559                                                     SILC_STATUS_OK, ident, 2,
3560                                                     2, idp, idp->len,
3561                                                     3, entry->motd,
3562                                                     strlen(entry->motd));
3563     else
3564       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3565                                                     SILC_STATUS_OK, ident, 1,
3566                                                     2, idp, idp->len);
3567
3568     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3569                             packet->data, packet->len, FALSE);
3570     silc_buffer_free(packet);
3571     silc_buffer_free(idp);
3572   }
3573
3574  out:
3575   silc_server_command_free(cmd);
3576 }
3577
3578 /* Server side of command UMODE. Client can use this command to set/unset
3579    user mode. Client actually cannot set itself to be as server/router
3580    operator so this can be used only to unset the modes. */
3581
3582 SILC_SERVER_CMD_FUNC(umode)
3583 {
3584   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3585   SilcServer server = cmd->server;
3586   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3587   SilcBuffer packet;
3588   unsigned char *tmp_mask;
3589   uint32 mask;
3590   uint16 ident = silc_command_get_ident(cmd->payload);
3591
3592   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3593     goto out;
3594
3595   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3596
3597   /* Get the client's mode mask */
3598   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3599   if (!tmp_mask) {
3600     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3601                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3602     goto out;
3603   }
3604   SILC_GET32_MSB(mask, tmp_mask);
3605
3606   /* 
3607    * Change the mode 
3608    */
3609
3610   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3611     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3612       /* Cannot operator mode */
3613       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3614                                             SILC_STATUS_ERR_PERM_DENIED);
3615       goto out;
3616     }
3617   } else {
3618     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3619       /* Remove the server operator rights */
3620       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3621   }
3622
3623   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3624     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3625       /* Cannot operator mode */
3626       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3627                                             SILC_STATUS_ERR_PERM_DENIED);
3628       goto out;
3629     }
3630   } else {
3631     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3632       /* Remove the router operator rights */
3633       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3634   }
3635
3636   if (mask & SILC_UMODE_GONE) {
3637     client->mode |= SILC_UMODE_GONE;
3638   } else {
3639     if (client->mode & SILC_UMODE_GONE)
3640       /* Remove the gone status */
3641       client->mode &= ~SILC_UMODE_GONE;
3642   }
3643
3644   /* Send UMODE change to primary router */
3645   if (!server->standalone)
3646     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3647                                   client->id, client->mode);
3648
3649   /* Send command reply to sender */
3650   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3651                                                 SILC_STATUS_OK, ident, 1,
3652                                                 2, tmp_mask, 4);
3653   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3654                           packet->data, packet->len, FALSE);
3655   silc_buffer_free(packet);
3656
3657  out:
3658   silc_server_command_free(cmd);
3659 }
3660
3661 /* Checks that client has rights to add or remove channel modes. If any
3662    of the checks fails FALSE is returned. */
3663
3664 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3665                                    SilcChannelClientEntry client,
3666                                    uint32 mode)
3667 {
3668   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3669   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3670
3671   /* Check whether has rights to change anything */
3672   if (!is_op && !is_fo)
3673     return FALSE;
3674
3675   /* Check whether has rights to change everything */
3676   if (is_op && is_fo)
3677     return TRUE;
3678
3679   /* We know that client is channel operator, check that they are not
3680      changing anything that requires channel founder rights. Rest of the
3681      modes are available automatically for channel operator. */
3682
3683   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3684     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3685       if (is_op && !is_fo)
3686         return FALSE;
3687   } else {
3688     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3689       if (is_op && !is_fo)
3690         return FALSE;
3691     }
3692   }
3693   
3694   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3695     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3696       if (is_op && !is_fo)
3697         return FALSE;
3698   } else {
3699     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3700       if (is_op && !is_fo)
3701         return FALSE;
3702     }
3703   }
3704
3705   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3706     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3707       if (is_op && !is_fo)
3708         return FALSE;
3709   } else {
3710     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3711       if (is_op && !is_fo)
3712         return FALSE;
3713     }
3714   }
3715   
3716   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3717     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3718       if (is_op && !is_fo)
3719         return FALSE;
3720   } else {
3721     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3722       if (is_op && !is_fo)
3723         return FALSE;
3724     }
3725   }
3726   
3727   return TRUE;
3728 }
3729
3730 /* Server side command of CMODE. Changes channel mode */
3731
3732 SILC_SERVER_CMD_FUNC(cmode)
3733 {
3734   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3735   SilcServer server = cmd->server;
3736   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3737   SilcIDListData idata = (SilcIDListData)client;
3738   SilcChannelID *channel_id;
3739   SilcChannelEntry channel;
3740   SilcChannelClientEntry chl;
3741   SilcBuffer packet, cidp;
3742   unsigned char *tmp, *tmp_id, *tmp_mask;
3743   char *cipher = NULL, *hmac = NULL;
3744   uint32 mode_mask, tmp_len, tmp_len2;
3745   uint16 ident = silc_command_get_ident(cmd->payload);
3746
3747   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3748
3749   /* Get Channel ID */
3750   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3751   if (!tmp_id) {
3752     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3753                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3754     goto out;
3755   }
3756   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3757   if (!channel_id) {
3758     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3759                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3760     goto out;
3761   }
3762
3763   /* Get the channel mode mask */
3764   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3765   if (!tmp_mask) {
3766     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3767                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3768     goto out;
3769   }
3770   SILC_GET32_MSB(mode_mask, tmp_mask);
3771
3772   /* Get channel entry */
3773   channel = silc_idlist_find_channel_by_id(server->local_list, 
3774                                            channel_id, NULL);
3775   if (!channel) {
3776     channel = silc_idlist_find_channel_by_id(server->global_list, 
3777                                              channel_id, NULL);
3778     if (!channel) {
3779       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3780                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3781       goto out;
3782     }
3783   }
3784
3785   /* Check whether this client is on the channel */
3786   if (!silc_server_client_on_channel(client, channel)) {
3787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3789     goto out;
3790   }
3791
3792   /* Get entry to the channel user list */
3793   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3794
3795   /* Check that client has rights to change any requested channel modes */
3796   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3797     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3798                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3799     goto out;
3800   }
3801
3802   /*
3803    * Check the modes. Modes that requires nothing special operation are
3804    * not checked here.
3805    */
3806
3807   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3808     /* Channel uses private keys to protect traffic. Client(s) has set the
3809        key locally they want to use, server does not know that key. */
3810     /* Nothing interesting to do here */
3811   } else {
3812     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3813       /* The mode is removed and we need to generate and distribute
3814          new channel key. Clients are not using private channel keys
3815          anymore after this. */
3816
3817       /* Re-generate channel key */
3818       if (!silc_server_create_channel_key(server, channel, 0))
3819         goto out;
3820       
3821       /* Send the channel key. This sends it to our local clients and if
3822          we are normal server to our router as well. */
3823       silc_server_send_channel_key(server, NULL, channel, 
3824                                    server->server_type == SILC_ROUTER ? 
3825                                    FALSE : !server->standalone);
3826
3827       cipher = channel->channel_key->cipher->name;
3828       hmac = (char *)silc_hmac_get_name(channel->hmac);
3829     }
3830   }
3831   
3832   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3833     /* User limit is set on channel */
3834     uint32 user_limit;
3835       
3836     /* Get user limit */
3837     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3838     if (!tmp) {
3839       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3840         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3841                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3842         goto out;
3843       }
3844     } else {
3845       SILC_GET32_MSB(user_limit, tmp);
3846       channel->user_limit = user_limit;
3847     }
3848   } else {
3849     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3850       /* User limit mode is unset. Remove user limit */
3851       channel->user_limit = 0;
3852   }
3853
3854   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3855     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3856       /* Passphrase has been set to channel */
3857       
3858       /* Get the passphrase */
3859       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3860       if (!tmp) {
3861         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3862                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3863         goto out;
3864       }
3865
3866       /* Save the passphrase */
3867       channel->passphrase = strdup(tmp);
3868     }
3869   } else {
3870     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3871       /* Passphrase mode is unset. remove the passphrase */
3872       if (channel->passphrase) {
3873         silc_free(channel->passphrase);
3874         channel->passphrase = NULL;
3875       }
3876     }
3877   }
3878
3879   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3880     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3881       /* Cipher to use protect the traffic */
3882       SilcCipher newkey, oldkey;
3883
3884       /* Get cipher */
3885       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3886       if (!cipher) {
3887         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3888                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3889         goto out;
3890       }
3891
3892       /* Delete old cipher and allocate the new one */
3893       if (!silc_cipher_alloc(cipher, &newkey)) {
3894         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3895                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3896         goto out;
3897       }
3898
3899       oldkey = channel->channel_key;
3900       channel->channel_key = newkey;
3901
3902       /* Re-generate channel key */
3903       if (!silc_server_create_channel_key(server, channel, 0)) {
3904         /* We don't have new key, revert to old one */
3905         channel->channel_key = oldkey;
3906         goto out;
3907       }
3908
3909       /* Remove old channel key for good */
3910       silc_cipher_free(oldkey);
3911
3912       /* Send the channel key. This sends it to our local clients and if
3913          we are normal server to our router as well. */
3914       silc_server_send_channel_key(server, NULL, channel, 
3915                                    server->server_type == SILC_ROUTER ? 
3916                                    FALSE : !server->standalone);
3917     }
3918   } else {
3919     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3920       /* Cipher mode is unset. Remove the cipher and revert back to 
3921          default cipher */
3922       SilcCipher newkey, oldkey;
3923       cipher = channel->cipher;
3924
3925       /* Delete old cipher and allocate default one */
3926       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3927         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3928                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3929         goto out;
3930       }
3931
3932       oldkey = channel->channel_key;
3933       channel->channel_key = newkey;
3934
3935       /* Re-generate channel key */
3936       if (!silc_server_create_channel_key(server, channel, 0)) {
3937         /* We don't have new key, revert to old one */
3938         channel->channel_key = oldkey;
3939         goto out;
3940       }
3941       
3942       /* Remove old channel key for good */
3943       silc_cipher_free(oldkey);
3944
3945       /* Send the channel key. This sends it to our local clients and if
3946          we are normal server to our router as well. */
3947       silc_server_send_channel_key(server, NULL, channel, 
3948                                    server->server_type == SILC_ROUTER ? 
3949                                    FALSE : !server->standalone);
3950     }
3951   }
3952
3953   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3954     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3955       /* HMAC to use protect the traffic */
3956       unsigned char hash[32];
3957       SilcHmac newhmac;
3958
3959       /* Get hmac */
3960       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3961       if (!hmac) {
3962         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3964         goto out;
3965       }
3966
3967       /* Delete old hmac and allocate the new one */
3968       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3969         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3970                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3971         goto out;
3972       }
3973
3974       silc_hmac_free(channel->hmac);
3975       channel->hmac = newhmac;
3976
3977       /* Set the HMAC key out of current channel key. The client must do
3978          this locally. */
3979       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3980                      channel->key_len / 8, hash);
3981       silc_hmac_set_key(channel->hmac, hash, 
3982                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3983       memset(hash, 0, sizeof(hash));
3984     }
3985   } else {
3986     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3987       /* Hmac mode is unset. Remove the hmac and revert back to 
3988          default hmac */
3989       SilcHmac newhmac;
3990       unsigned char hash[32];
3991       hmac = channel->hmac_name;
3992
3993       /* Delete old hmac and allocate default one */
3994       silc_hmac_free(channel->hmac);
3995       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3996         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3997                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3998         goto out;
3999       }
4000
4001       silc_hmac_free(channel->hmac);
4002       channel->hmac = newhmac;
4003
4004       /* Set the HMAC key out of current channel key. The client must do
4005          this locally. */
4006       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4007                      channel->key_len / 8, 
4008                      hash);
4009       silc_hmac_set_key(channel->hmac, hash, 
4010                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4011       memset(hash, 0, sizeof(hash));
4012     }
4013   }
4014
4015   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4016     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4017       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4018         /* Set the founder authentication */
4019         SilcAuthPayload auth;
4020         
4021         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4022         if (!tmp) {
4023           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4024                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4025           goto out;
4026         }
4027
4028         auth = silc_auth_payload_parse(tmp, tmp_len);
4029         if (!auth) {
4030           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4031                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4032           goto out;
4033         }
4034
4035         /* Save the public key */
4036         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4037         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4038         silc_free(tmp);
4039         
4040         channel->founder_method = silc_auth_get_method(auth);
4041
4042         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4043           tmp = silc_auth_get_data(auth, &tmp_len);
4044           channel->founder_passwd = 
4045             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4046           memcpy(channel->founder_passwd, tmp, tmp_len);
4047           channel->founder_passwd_len = tmp_len;
4048         } else {
4049           /* Verify the payload before setting the mode */
4050           if (!silc_auth_verify(auth, channel->founder_method, 
4051                                 channel->founder_key, 0, idata->hash,
4052                                 client->id, SILC_ID_CLIENT)) {
4053             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4054                                                   SILC_STATUS_ERR_AUTH_FAILED);
4055             goto out;
4056           }
4057         }
4058
4059         silc_auth_payload_free(auth);
4060       }
4061     }
4062   } else {
4063     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4064       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4065         if (channel->founder_key)
4066           silc_pkcs_public_key_free(channel->founder_key);
4067         if (channel->founder_passwd) {
4068           silc_free(channel->founder_passwd);
4069           channel->founder_passwd = NULL;
4070         }
4071       }
4072     }
4073   }
4074
4075   /* Finally, set the mode */
4076   channel->mode = mode_mask;
4077
4078   /* Send CMODE_CHANGE notify */
4079   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4080   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4081                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4082                                      cidp->data, cidp->len, 
4083                                      tmp_mask, 4,
4084                                      cipher, cipher ? strlen(cipher) : 0,
4085                                      hmac, hmac ? strlen(hmac) : 0);
4086
4087   /* Set CMODE notify type to network */
4088   if (!server->standalone)
4089     silc_server_send_notify_cmode(server, server->router->connection,
4090                                   server->server_type == SILC_ROUTER ? 
4091                                   TRUE : FALSE, channel,
4092                                   mode_mask, client->id, SILC_ID_CLIENT,
4093                                   cipher, hmac);
4094
4095   /* Send command reply to sender */
4096   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4097                                                 SILC_STATUS_OK, ident, 2,
4098                                                 2, tmp_id, tmp_len2,
4099                                                 3, tmp_mask, 4);
4100   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4101                           packet->data, packet->len, FALSE);
4102     
4103   silc_buffer_free(packet);
4104   silc_free(channel_id);
4105   silc_free(cidp);
4106
4107  out:
4108   silc_server_command_free(cmd);
4109 }
4110
4111 /* Server side of CUMODE command. Changes client's mode on a channel. */
4112
4113 SILC_SERVER_CMD_FUNC(cumode)
4114 {
4115   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4116   SilcServer server = cmd->server;
4117   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4118   SilcIDListData idata = (SilcIDListData)client;
4119   SilcChannelID *channel_id;
4120   SilcClientID *client_id;
4121   SilcChannelEntry channel;
4122   SilcClientEntry target_client;
4123   SilcChannelClientEntry chl;
4124   SilcBuffer packet, idp;
4125   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4126   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4127   int notify = FALSE;
4128   uint16 ident = silc_command_get_ident(cmd->payload);
4129
4130   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4131
4132   /* Get Channel ID */
4133   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4134   if (!tmp_ch_id) {
4135     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4136                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4137     goto out;
4138   }
4139   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4140   if (!channel_id) {
4141     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4142                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4143     goto out;
4144   }
4145
4146   /* Get channel entry */
4147   channel = silc_idlist_find_channel_by_id(server->local_list, 
4148                                            channel_id, NULL);
4149   if (!channel) {
4150     channel = silc_idlist_find_channel_by_id(server->global_list, 
4151                                              channel_id, NULL);
4152     if (!channel) {
4153       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4154                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4155       goto out;
4156     }
4157   }
4158
4159   /* Check whether sender is on the channel */
4160   if (!silc_server_client_on_channel(client, channel)) {
4161     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4162                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4163     goto out;
4164   }
4165
4166   /* Check that client has rights to change other's rights */
4167   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4168   sender_mask = chl->mode;
4169   
4170   /* Get the target client's channel mode mask */
4171   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4172   if (!tmp_mask) {
4173     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4174                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4175     goto out;
4176   }
4177   SILC_GET32_MSB(target_mask, tmp_mask);
4178
4179   /* Get target Client ID */
4180   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4181   if (!tmp_id) {
4182     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4183                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4184     goto out;
4185   }
4186   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4187   if (!client_id) {
4188     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4189                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4190     goto out;
4191   }
4192
4193   /* Get target client's entry */
4194   target_client = silc_idlist_find_client_by_id(server->local_list, 
4195                                                 client_id, TRUE, NULL);
4196   if (!target_client) {
4197     target_client = silc_idlist_find_client_by_id(server->global_list, 
4198                                                   client_id, TRUE, NULL);
4199   }
4200
4201   if (target_client != client &&
4202       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4203       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4204     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4206     goto out;
4207   }
4208
4209   /* Check whether target client is on the channel */
4210   if (target_client != client) {
4211     if (!silc_server_client_on_channel(target_client, channel)) {
4212       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4214       goto out;
4215     }
4216
4217     /* Get entry to the channel user list */
4218     silc_hash_table_find(channel->user_list, target_client, NULL, 
4219                          (void *)&chl);
4220   }
4221
4222   /* 
4223    * Change the mode 
4224    */
4225
4226   /* If the target client is founder, no one else can change their mode
4227      but themselves. */
4228   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4229     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4230                                           SILC_STATUS_ERR_NOT_YOU);
4231     goto out;
4232   }
4233
4234   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4235     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4236       /* The client tries to claim the founder rights. */
4237       unsigned char *tmp_auth;
4238       uint32 tmp_auth_len, auth_len;
4239       void *auth;
4240       
4241       if (target_client != client) {
4242         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4243                                               SILC_STATUS_ERR_NOT_YOU);
4244         goto out;
4245       }
4246
4247       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4248           !channel->founder_key || !idata->public_key ||
4249           !silc_pkcs_public_key_compare(channel->founder_key, 
4250                                         idata->public_key)) {
4251         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4252                                               SILC_STATUS_ERR_NOT_YOU);
4253         goto out;
4254       }
4255
4256       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4257       if (!tmp_auth) {
4258         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4259                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4260         goto out;
4261       }
4262
4263       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4264               (void *)channel->founder_passwd : (void *)channel->founder_key);
4265       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4266                   channel->founder_passwd_len : 0);
4267       
4268       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4269                                  channel->founder_method, auth, auth_len,
4270                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4271         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4272                                               SILC_STATUS_ERR_AUTH_FAILED);
4273         goto out;
4274       }
4275       
4276       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4277       notify = TRUE;
4278     }
4279   } else {
4280     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4281       if (target_client == client) {
4282         /* Remove channel founder rights from itself */
4283         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4284         notify = TRUE;
4285       } else {
4286         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287                                               SILC_STATUS_ERR_NOT_YOU);
4288         goto out;
4289       }
4290     }
4291   }
4292
4293   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4294     /* Promote to operator */
4295     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4296       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4297           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4298         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4299                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4300         goto out;
4301       }
4302
4303       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4304       notify = TRUE;
4305     }
4306   } else {
4307     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4308       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4309           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4310         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4311                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4312         goto out;
4313       }
4314
4315       /* Demote to normal user */
4316       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4317       notify = TRUE;
4318     }
4319   }
4320
4321   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4322   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4323
4324   /* Send notify to channel, notify only if mode was actually changed. */
4325   if (notify) {
4326     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4327                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4328                                        idp->data, idp->len,
4329                                        tmp_mask, 4, 
4330                                        tmp_id, tmp_len);
4331
4332     /* Set CUMODE notify type to network */
4333     if (!server->standalone)
4334       silc_server_send_notify_cumode(server, server->router->connection,
4335                                      server->server_type == SILC_ROUTER ? 
4336                                      TRUE : FALSE, channel,
4337                                      target_mask, client->id, 
4338                                      SILC_ID_CLIENT,
4339                                      target_client->id);
4340   }
4341
4342   /* Send command reply to sender */
4343   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4344                                                 SILC_STATUS_OK, ident, 3,
4345                                                 2, tmp_mask, 4,
4346                                                 3, tmp_ch_id, tmp_ch_len,
4347                                                 4, tmp_id, tmp_len);
4348   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4349                           packet->data, packet->len, FALSE);
4350     
4351   silc_buffer_free(packet);
4352   silc_free(channel_id);
4353   silc_free(client_id);
4354   silc_buffer_free(idp);
4355
4356  out:
4357   silc_server_command_free(cmd);
4358 }
4359
4360 /* Server side of KICK command. Kicks client out of channel. */
4361
4362 SILC_SERVER_CMD_FUNC(kick)
4363 {
4364   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4365   SilcServer server = cmd->server;
4366   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4367   SilcClientEntry target_client;
4368   SilcChannelID *channel_id;
4369   SilcClientID *client_id;
4370   SilcChannelEntry channel;
4371   SilcChannelClientEntry chl;
4372   SilcBuffer idp;
4373   uint32 tmp_len;
4374   unsigned char *tmp, *comment;
4375
4376   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4377
4378   /* Get Channel ID */
4379   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4380   if (!tmp) {
4381     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4382                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4383     goto out;
4384   }
4385   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4386   if (!channel_id) {
4387     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4388                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4389     goto out;
4390   }
4391
4392   /* Get channel entry */
4393   channel = silc_idlist_find_channel_by_id(server->local_list, 
4394                                            channel_id, NULL);
4395   if (!channel) {
4396     channel = silc_idlist_find_channel_by_id(server->local_list, 
4397                                              channel_id, NULL);
4398     if (!channel) {
4399       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4400                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4401       goto out;
4402     }
4403   }
4404
4405   /* Check whether sender is on the channel */
4406   if (!silc_server_client_on_channel(client, channel)) {
4407     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4408                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4409     goto out;
4410   }
4411
4412   /* Check that the kicker is channel operator or channel founder */
4413   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4414   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4415     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4416                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4417     goto out;
4418   }
4419   
4420   /* Get target Client ID */
4421   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4422   if (!tmp) {
4423     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4424                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4425     goto out;
4426   }
4427   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4428   if (!client_id) {
4429     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4430                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4431     goto out;
4432   }
4433
4434   /* Get target client's entry */
4435   target_client = silc_idlist_find_client_by_id(server->local_list, 
4436                                                 client_id, TRUE, NULL);
4437   if (!target_client) {
4438     target_client = silc_idlist_find_client_by_id(server->global_list, 
4439                                                   client_id, TRUE, NULL);
4440   }
4441
4442   /* Check that the target client is not channel founder. Channel founder
4443      cannot be kicked from the channel. */
4444   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4445   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4446     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4447                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4448     goto out;
4449   }
4450   
4451   /* Check whether target client is on the channel */
4452   if (!silc_server_client_on_channel(target_client, channel)) {
4453     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4454                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4455     goto out;
4456   }
4457
4458   /* Get comment */
4459   tmp_len = 0;
4460   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4461   if (tmp_len > 128)
4462     comment = NULL;
4463
4464   /* Send command reply to sender */
4465   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4466                                         SILC_STATUS_OK);
4467
4468   /* Send KICKED notify to local clients on the channel */
4469   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4470   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4471                                      SILC_NOTIFY_TYPE_KICKED, 
4472                                      comment ? 2 : 1,
4473                                      idp->data, idp->len,
4474                                      comment, comment ? strlen(comment) : 0);
4475   silc_buffer_free(idp);
4476
4477   /* Remove the client from the channel. If the channel does not exist
4478      after removing the client then the client kicked itself off the channel
4479      and we don't have to send anything after that. */
4480   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4481                                            target_client, FALSE))
4482     goto out;
4483
4484   /* Send KICKED notify to primary route */
4485   if (!server->standalone)
4486     silc_server_send_notify_kicked(server, server->router->connection,
4487                                    server->server_type == SILC_ROUTER ?
4488                                    TRUE : FALSE, channel,
4489                                    target_client->id, comment);
4490
4491   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4492     /* Re-generate channel key */
4493     if (!silc_server_create_channel_key(server, channel, 0))
4494       goto out;
4495     
4496     /* Send the channel key to the channel. The key of course is not sent
4497        to the client who was kicked off the channel. */
4498     silc_server_send_channel_key(server, target_client->connection, channel, 
4499                                  server->server_type == SILC_ROUTER ? 
4500                                  FALSE : !server->standalone);
4501   }
4502
4503  out:
4504   silc_server_command_free(cmd);
4505 }
4506
4507 /* Server side of OPER command. Client uses this comand to obtain server
4508    operator privileges to this server/router. */
4509
4510 SILC_SERVER_CMD_FUNC(oper)
4511 {
4512   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4513   SilcServer server = cmd->server;
4514   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4515   unsigned char *username, *auth;
4516   uint32 tmp_len;
4517   SilcServerConfigSectionAdminConnection *admin;
4518   SilcIDListData idata = (SilcIDListData)client;
4519
4520   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4521
4522   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4523     goto out;
4524
4525   /* Get the username */
4526   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4527   if (!username) {
4528     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4529                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4530     goto out;
4531   }
4532
4533   /* Get the admin configuration */
4534   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4535                                         username, client->nickname);
4536   if (!admin) {
4537     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4538                                           username, client->nickname);
4539     if (!admin) {
4540       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4541                                             SILC_STATUS_ERR_AUTH_FAILED);
4542       goto out;
4543     }
4544   }
4545
4546   /* Get the authentication payload */
4547   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4548   if (!auth) {
4549     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4550                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4551     goto out;
4552   }
4553
4554   /* Verify the authentication data */
4555   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4556                              admin->auth_data, admin->auth_data_len,
4557                              idata->hash, client->id, SILC_ID_CLIENT)) {
4558     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4559                                           SILC_STATUS_ERR_AUTH_FAILED);
4560     goto out;
4561   }
4562
4563   /* Client is now server operator */
4564   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4565
4566   /* Send UMODE change to primary router */
4567   if (!server->standalone)
4568     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4569                                   client->id, client->mode);
4570
4571   /* Send reply to the sender */
4572   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4573                                         SILC_STATUS_OK);
4574
4575  out:
4576   silc_server_command_free(cmd);
4577 }
4578
4579 /* Server side of SILCOPER command. Client uses this comand to obtain router
4580    operator privileges to this router. */
4581
4582 SILC_SERVER_CMD_FUNC(silcoper)
4583 {
4584   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4585   SilcServer server = cmd->server;
4586   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4587   unsigned char *username, *auth;
4588   uint32 tmp_len;
4589   SilcServerConfigSectionAdminConnection *admin;
4590   SilcIDListData idata = (SilcIDListData)client;
4591
4592   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4593
4594   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4595     goto out;
4596
4597   if (server->server_type != SILC_ROUTER) {
4598     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4599                                           SILC_STATUS_ERR_AUTH_FAILED);
4600     goto out;
4601   }
4602
4603   /* Get the username */
4604   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4605   if (!username) {
4606     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4607                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4608     goto out;
4609   }
4610
4611   /* Get the admin configuration */
4612   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4613                                         username, client->nickname);
4614   if (!admin) {
4615     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4616                                           username, client->nickname);
4617     if (!admin) {
4618       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4619                                             SILC_STATUS_ERR_AUTH_FAILED);
4620       goto out;
4621     }
4622   }
4623
4624   /* Get the authentication payload */
4625   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4626   if (!auth) {
4627     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4628                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4629     goto out;
4630   }
4631
4632   /* Verify the authentication data */
4633   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4634                              admin->auth_data, admin->auth_data_len,
4635                              idata->hash, client->id, SILC_ID_CLIENT)) {
4636     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4637                                           SILC_STATUS_ERR_AUTH_FAILED);
4638     goto out;
4639   }
4640
4641   /* Client is now router operator */
4642   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4643
4644   /* Send UMODE change to primary router */
4645   if (!server->standalone)
4646     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4647                                   client->id, client->mode);
4648
4649   /* Send reply to the sender */
4650   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4651                                         SILC_STATUS_OK);
4652
4653  out:
4654   silc_server_command_free(cmd);
4655 }
4656
4657 /* Server side command of CONNECT. Connects us to the specified remote
4658    server or router. */
4659
4660 SILC_SERVER_CMD_FUNC(connect)
4661 {
4662   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4663   SilcServer server = cmd->server;
4664   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4665   unsigned char *tmp, *host;
4666   uint32 tmp_len;
4667   uint32 port = SILC_PORT;
4668
4669   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4670
4671   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4672     goto out;
4673
4674   /* Check whether client has the permissions. */
4675   if (client->mode == SILC_UMODE_NONE) {
4676     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4677                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4678     goto out;
4679   }
4680
4681   if (server->server_type == SILC_ROUTER && 
4682       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4683     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4684                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4685     goto out;
4686   }
4687
4688   /* Get the remote server */
4689   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4690   if (!host) {
4691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4692                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4693     goto out;
4694   }
4695
4696   /* Get port */
4697   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4698   if (tmp)
4699     SILC_GET32_MSB(port, tmp);
4700
4701   /* Create the connection. It is done with timeout and is async. */
4702   silc_server_create_connection(server, host, port);
4703
4704   /* Send reply to the sender */
4705   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4706                                         SILC_STATUS_OK);
4707
4708  out:
4709   silc_server_command_free(cmd);
4710 }
4711
4712 /* Server side of command BAN. This is used to manage the ban list of the
4713    channel. To add clients and remove clients from the ban list. */
4714
4715 SILC_SERVER_CMD_FUNC(ban)
4716 {
4717   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4718   SilcServer server = cmd->server;
4719   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4720   SilcBuffer packet;
4721   SilcChannelEntry channel;
4722   SilcChannelClientEntry chl;
4723   SilcChannelID *channel_id = NULL;
4724   unsigned char *id, *add, *del;
4725   uint32 id_len, tmp_len;
4726   uint16 ident = silc_command_get_ident(cmd->payload);
4727
4728   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4729     goto out;
4730
4731   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4732
4733   /* Get Channel ID */
4734   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4735   if (id) {
4736     channel_id = silc_id_payload_parse_id(id, id_len);
4737     if (!channel_id) {
4738       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4739                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4740       goto out;
4741     }
4742   }
4743
4744   /* Get channel entry. The server must know about the channel since the
4745      client is expected to be on the channel. */
4746   channel = silc_idlist_find_channel_by_id(server->local_list, 
4747                                            channel_id, NULL);
4748   if (!channel) {
4749     channel = silc_idlist_find_channel_by_id(server->global_list, 
4750                                              channel_id, NULL);
4751     if (!channel) {
4752       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4753                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4754       goto out;
4755     }
4756   }
4757
4758   /* Check whether this client is on the channel */
4759   if (!silc_server_client_on_channel(client, channel)) {
4760     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4761                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4762     goto out;
4763   }
4764
4765   /* Get entry to the channel user list */
4766   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4767
4768   /* The client must be at least channel operator. */
4769   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4770     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4771                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4772     goto out;
4773   }
4774
4775   /* Get the new ban and add it to the ban list */
4776   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4777   if (add) {
4778     if (!channel->ban_list)
4779       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4780     else
4781       channel->ban_list = silc_realloc(channel->ban_list, 
4782                                        sizeof(*channel->ban_list) * 
4783                                        (tmp_len + 
4784                                         strlen(channel->ban_list) + 2));
4785     if (add[tmp_len - 1] == ',')
4786       add[tmp_len - 1] = '\0';
4787
4788     strncat(channel->ban_list, add, tmp_len);
4789     strncat(channel->ban_list, ",", 1);
4790   }
4791
4792   /* Get the ban to be removed and remove it from the list */
4793   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4794   if (del && channel->ban_list) {
4795     char *start, *end, *n;
4796
4797     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4798       silc_free(channel->ban_list);
4799       channel->ban_list = NULL;
4800     } else {
4801       start = strstr(channel->ban_list, del);
4802       if (start && strlen(start) >= tmp_len) {
4803         end = start + tmp_len;
4804         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4805         strncat(n, channel->ban_list, start - channel->ban_list);
4806         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4807                              end) - 1);
4808         silc_free(channel->ban_list);
4809         channel->ban_list = n;
4810       }
4811     }
4812   }
4813
4814   /* Send the BAN notify type to our primary router. */
4815   if (!server->standalone && (add || del))
4816     silc_server_send_notify_ban(server, server->router->connection,
4817                                 server->server_type == SILC_ROUTER ?
4818                                 TRUE : FALSE, channel, add, del);
4819
4820   /* Send the reply back to the client */
4821   if (channel->ban_list)
4822     packet = 
4823       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4824                                            SILC_STATUS_OK, ident, 2,
4825                                            2, id, id_len,
4826                                            3, channel->ban_list, 
4827                                            strlen(channel->ban_list) - 1);
4828   else
4829     packet = 
4830       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4831                                            SILC_STATUS_OK, ident, 1,
4832                                            2, id, id_len);
4833
4834   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4835                           packet->data, packet->len, FALSE);
4836     
4837   silc_buffer_free(packet);
4838
4839  out:
4840   silc_free(channel_id);
4841   silc_server_command_free(cmd);
4842 }
4843
4844 /* Server side command of CLOSE. Closes connection to a specified server. */
4845  
4846 SILC_SERVER_CMD_FUNC(close)
4847 {
4848   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4849   SilcServer server = cmd->server;
4850   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4851   SilcServerEntry server_entry;
4852   SilcSocketConnection sock;
4853   unsigned char *tmp;
4854   uint32 tmp_len;
4855   unsigned char *name;
4856   uint32 port = SILC_PORT;
4857
4858   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4859
4860   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4861     goto out;
4862
4863   /* Check whether client has the permissions. */
4864   if (client->mode == SILC_UMODE_NONE) {
4865     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4866                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4867     goto out;
4868   }
4869
4870   /* Get the remote server */
4871   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4872   if (!name) {
4873     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4874                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4875     goto out;
4876   }
4877
4878   /* Get port */
4879   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4880   if (tmp)
4881     SILC_GET32_MSB(port, tmp);
4882
4883   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4884                                                  name, port, FALSE, NULL);
4885   if (!server_entry)
4886     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4887                                                    name, port, FALSE, NULL);
4888   if (!server_entry) {
4889     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4890                                           SILC_STATUS_ERR_NO_SERVER_ID);
4891     goto out;
4892   }
4893
4894   /* Send reply to the sender */
4895   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4896                                         SILC_STATUS_OK);
4897
4898   /* Close the connection to the server */
4899   sock = (SilcSocketConnection)server_entry->connection;
4900
4901   /* If we shutdown primary router connection manually then don't trigger
4902      any reconnect or backup router connections, by setting the router
4903      to NULL here. */
4904   if (server->router == server_entry) {
4905     server->id_entry->router = NULL;
4906     server->router = NULL;
4907     server->standalone = TRUE;
4908   }
4909   silc_server_free_sock_user_data(server, sock);
4910   silc_server_close_connection(server, sock);
4911   
4912  out:
4913   silc_server_command_free(cmd);
4914 }
4915
4916 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4917    active connections. */
4918  
4919 SILC_SERVER_CMD_FUNC(shutdown)
4920 {
4921   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4922   SilcServer server = cmd->server;
4923   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4924
4925   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4926
4927   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4928     goto out;
4929
4930   /* Check whether client has the permission. */
4931   if (client->mode == SILC_UMODE_NONE) {
4932     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4933                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4934     goto out;
4935   }
4936
4937   /* Send reply to the sender */
4938   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4939                                         SILC_STATUS_OK);
4940
4941   /* Then, gracefully, or not, bring the server down. */
4942   silc_server_stop(server);
4943   exit(0);
4944
4945  out:
4946   silc_server_command_free(cmd);
4947 }
4948  
4949 /* Server side command of LEAVE. Removes client from a channel. */
4950
4951 SILC_SERVER_CMD_FUNC(leave)
4952 {
4953   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4954   SilcServer server = cmd->server;
4955   SilcSocketConnection sock = cmd->sock;
4956   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4957   SilcChannelID *id = NULL;
4958   SilcChannelEntry channel;
4959   uint32 len;
4960   unsigned char *tmp;
4961
4962   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4963
4964   /* Get Channel ID */
4965   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4966   if (!tmp) {
4967     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4968                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4969     goto out;
4970   }
4971   id = silc_id_payload_parse_id(tmp, len);
4972   if (!id) {
4973     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4974                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4975     goto out;
4976   }
4977
4978   /* Get channel entry */
4979   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4980   if (!channel) {
4981     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4982     if (!channel) {
4983       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4984                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4985       goto out;
4986     }
4987   }
4988
4989   /* Check whether this client is on the channel */
4990   if (!silc_server_client_on_channel(id_entry, channel)) {
4991     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4992                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4993     goto out;
4994   }
4995
4996   /* Notify routers that they should remove this client from their list
4997      of clients on the channel. Send LEAVE notify type. */
4998   if (!server->standalone)
4999     silc_server_send_notify_leave(server, server->router->connection,
5000                                   server->server_type == SILC_ROUTER ?
5001                                   TRUE : FALSE, channel, id_entry->id);
5002
5003   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5004                                         SILC_STATUS_OK);
5005
5006   /* Remove client from channel */
5007   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5008                                            TRUE))
5009     /* If the channel does not exist anymore we won't send anything */
5010     goto out;
5011
5012   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5013     /* Re-generate channel key */
5014     if (!silc_server_create_channel_key(server, channel, 0))
5015       goto out;
5016
5017     /* Send the channel key */
5018     silc_server_send_channel_key(server, NULL, channel, 
5019                                  server->server_type == SILC_ROUTER ? 
5020                                  FALSE : !server->standalone);
5021   }
5022
5023  out:
5024   silc_free(id);
5025   silc_server_command_free(cmd);
5026 }
5027
5028 /* Server side of command USERS. Resolves clients and their USERS currently
5029    joined on the requested channel. The list of Client ID's and their modes
5030    on the channel is sent back. */
5031
5032 SILC_SERVER_CMD_FUNC(users)
5033 {
5034   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5035   SilcServer server = cmd->server;
5036   SilcChannelEntry channel;
5037   SilcChannelID *id = NULL;
5038   SilcBuffer packet, idp;
5039   unsigned char *channel_id;
5040   uint32 channel_id_len;
5041   SilcBuffer client_id_list;
5042   SilcBuffer client_mode_list;
5043   unsigned char lc[4];
5044   uint32 list_count = 0;
5045   uint16 ident = silc_command_get_ident(cmd->payload);
5046   char *channel_name;
5047
5048   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5049
5050   /* Get Channel ID */
5051   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5052
5053   /* Get channel name */
5054   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5055
5056   if (!channel_id && !channel_name) {
5057     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5058                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5059     goto out;
5060   }
5061
5062   if (channel_id) {
5063     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5064     if (!id) {
5065       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5066                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5067       goto out;
5068     }
5069   }
5070
5071   /* If we are server and we don't know about this channel we will send
5072      the command to our router. If we know about the channel then we also
5073      have the list of users already. */
5074   if (id)
5075     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5076   else
5077     channel = silc_idlist_find_channel_by_name(server->local_list, 
5078                                                channel_name, NULL);
5079
5080   if (!channel || channel->disabled) {
5081     if (server->server_type != SILC_ROUTER && !server->standalone &&
5082         !cmd->pending) {
5083       SilcBuffer tmpbuf;
5084       
5085       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5086       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5087       
5088       /* Send USERS command */
5089       silc_server_packet_send(server, server->router->connection,
5090                               SILC_PACKET_COMMAND, cmd->packet->flags,
5091                               tmpbuf->data, tmpbuf->len, TRUE);
5092       
5093       /* Reprocess this packet after received reply */
5094       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5095                                   silc_command_get_ident(cmd->payload),
5096                                   silc_server_command_destructor,
5097                                   silc_server_command_users,
5098                                   silc_server_command_dup(cmd));
5099       cmd->pending = TRUE;
5100       silc_command_set_ident(cmd->payload, ident);
5101       
5102       silc_buffer_free(tmpbuf);
5103       silc_free(id);
5104       return;
5105     }
5106
5107     /* Check the global list as well. */
5108     if (id)
5109       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5110     else
5111       channel = silc_idlist_find_channel_by_name(server->global_list, 
5112                                                  channel_name, NULL);
5113     if (!channel) {
5114       /* Channel really does not exist */
5115       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5116                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5117       goto out;
5118     }
5119   }
5120
5121   /* If the channel is private or secret do not send anything, unless the
5122      user requesting this command is on the channel. */
5123   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5124     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5125         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5126       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5127                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5128       goto out;
5129     }
5130   } else {
5131     if (channel->mode & 
5132         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5133       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5134                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5135       goto out;
5136     }
5137   }
5138
5139   /* Get the users list */
5140   silc_server_get_users_on_channel(server, channel, &client_id_list,
5141                                    &client_mode_list, &list_count);
5142
5143   /* List count */
5144   SILC_PUT32_MSB(list_count, lc);
5145
5146   /* Send reply */
5147   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5148   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5149                                                 SILC_STATUS_OK, ident, 4,
5150                                                 2, idp->data, idp->len,
5151                                                 3, lc, 4,
5152                                                 4, client_id_list->data,
5153                                                 client_id_list->len,
5154                                                 5, client_mode_list->data,
5155                                                 client_mode_list->len);
5156   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5157                           packet->data, packet->len, FALSE);
5158     
5159   silc_buffer_free(idp);
5160   silc_buffer_free(packet);
5161   silc_buffer_free(client_id_list);
5162   silc_buffer_free(client_mode_list);
5163   silc_free(id);
5164
5165  out:
5166   silc_server_command_free(cmd);
5167 }
5168
5169 /* Server side of command GETKEY. This fetches the client's public key
5170    from the server where to the client is connected. */
5171
5172 SILC_SERVER_CMD_FUNC(getkey)
5173 {
5174   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5175   SilcServer server = cmd->server;
5176   SilcBuffer packet;
5177   SilcClientEntry client;
5178   SilcServerEntry server_entry;
5179   SilcClientID *client_id = NULL;
5180   SilcServerID *server_id = NULL;
5181   SilcIDPayload idp = NULL;
5182   uint16 ident = silc_command_get_ident(cmd->payload);
5183   unsigned char *tmp, *pkdata;
5184   uint32 tmp_len, pklen;
5185   SilcBuffer pk = NULL;
5186   SilcIdType id_type;
5187
5188   SILC_LOG_DEBUG(("Start"));
5189
5190   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5191   if (!tmp) {
5192     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5193                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5194     goto out;
5195   }
5196   idp = silc_id_payload_parse_data(tmp, tmp_len);
5197   if (!idp) {
5198     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5199                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5200     goto out;
5201   }
5202
5203   id_type = silc_id_payload_get_type(idp);
5204   if (id_type == SILC_ID_CLIENT) {
5205     client_id = silc_id_payload_get_id(idp);
5206
5207     /* If the client is not found from local list there is no chance it
5208        would be locally connected client so send the command further. */
5209     client = silc_idlist_find_client_by_id(server->local_list, 
5210                                            client_id, TRUE, NULL);
5211     if (!client)
5212       client = silc_idlist_find_client_by_id(server->global_list, 
5213                                              client_id, TRUE, NULL);
5214     
5215     if ((!client && !cmd->pending && !server->standalone) ||
5216         (client && !client->connection && !cmd->pending) ||
5217         (client && !client->data.public_key && !cmd->pending)) {
5218       SilcBuffer tmpbuf;
5219       uint16 old_ident;
5220       SilcSocketConnection dest_sock;
5221       
5222       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5223                                                client_id, NULL);
5224       if (!dest_sock)
5225         goto out;
5226       
5227       old_ident = silc_command_get_ident(cmd->payload);
5228       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5229       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5230       
5231       silc_server_packet_send(server, dest_sock,
5232                               SILC_PACKET_COMMAND, cmd->packet->flags,
5233                               tmpbuf->data, tmpbuf->len, TRUE);
5234       
5235       /* Reprocess this packet after received reply from router */
5236       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5237                                   silc_command_get_ident(cmd->payload),
5238                                   silc_server_command_destructor,
5239                                   silc_server_command_getkey,
5240                                   silc_server_command_dup(cmd));
5241       cmd->pending = TRUE;
5242       
5243       silc_command_set_ident(cmd->payload, old_ident);
5244       silc_buffer_free(tmpbuf);
5245       return;
5246     }
5247
5248     if (!client) {
5249       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5250                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5251       goto out;
5252     }
5253
5254     /* The client is locally connected, just get the public key and
5255        send it back. If they key does not exist then do not send it, 
5256        send just OK reply */
5257     if (!client->data.public_key) {
5258       pkdata = NULL;
5259       pklen = 0;
5260     } else {
5261       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5262       pk = silc_buffer_alloc(4 + tmp_len);
5263       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5264       silc_buffer_format(pk,
5265                          SILC_STR_UI_SHORT(tmp_len),
5266                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5267                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5268                          SILC_STR_END);
5269       silc_free(tmp);
5270       pkdata = pk->data;
5271       pklen = pk->len;
5272     }
5273   } else if (id_type == SILC_ID_SERVER) {
5274     server_id = silc_id_payload_get_id(idp);
5275
5276     /* If the server is not found from local list there is no chance it
5277        would be locally connected server so send the command further. */
5278     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5279                                                  server_id, TRUE, NULL);
5280     if (!server_entry)
5281       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5282                                                    server_id, TRUE, NULL);
5283     
5284     if (server_entry != server->id_entry &&
5285         ((!server_entry && !cmd->pending && !server->standalone) ||
5286          (server_entry && !server_entry->connection && !cmd->pending &&
5287           !server->standalone) ||
5288          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5289           !server->standalone))) {
5290       SilcBuffer tmpbuf;
5291       uint16 old_ident;
5292       
5293       old_ident = silc_command_get_ident(cmd->payload);
5294       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5295       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5296       
5297       silc_server_packet_send(server, server->router->connection,
5298                               SILC_PACKET_COMMAND, cmd->packet->flags,
5299                               tmpbuf->data, tmpbuf->len, TRUE);
5300       
5301       /* Reprocess this packet after received reply from router */
5302       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5303                                   silc_command_get_ident(cmd->payload),
5304                                   silc_server_command_destructor,
5305                                   silc_server_command_getkey,
5306                                   silc_server_command_dup(cmd));
5307       cmd->pending = TRUE;
5308       
5309       silc_command_set_ident(cmd->payload, old_ident);
5310       silc_buffer_free(tmpbuf);
5311       return;
5312     }
5313
5314     if (!server_entry) {
5315       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5316                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5317       goto out;
5318     }
5319
5320     /* If they key does not exist then do not send it, send just OK reply */
5321     if (!server_entry->data.public_key) {
5322       pkdata = NULL;
5323       pklen = 0;
5324     } else {
5325       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5326                                         &tmp_len);
5327       pk = silc_buffer_alloc(4 + tmp_len);
5328       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5329       silc_buffer_format(pk,
5330                          SILC_STR_UI_SHORT(tmp_len),
5331                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5332                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5333                          SILC_STR_END);
5334       silc_free(tmp);
5335       pkdata = pk->data;
5336       pklen = pk->len;
5337     }
5338   } else {
5339     goto out;
5340   }
5341
5342   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5343   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5344                                                 SILC_STATUS_OK, ident, 
5345                                                 pkdata ? 2 : 1,
5346                                                 2, tmp, tmp_len,
5347                                                 3, pkdata, pklen);
5348   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5349                           packet->data, packet->len, FALSE);
5350   silc_buffer_free(packet);
5351
5352   if (pk)
5353     silc_buffer_free(pk);
5354
5355  out:
5356   if (idp)
5357     silc_id_payload_free(idp);
5358   silc_free(client_id);
5359   silc_free(server_id);
5360   silc_server_command_free(cmd);
5361 }