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