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
3846       /* Get cipher */
3847       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3848       if (!cipher) {
3849         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3851         goto out;
3852       }
3853
3854       /* Delete old cipher and allocate the new one */
3855       silc_cipher_free(channel->channel_key);
3856       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3857         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3858                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3859         goto out;
3860       }
3861
3862       /* Re-generate channel key */
3863       if (!silc_server_create_channel_key(server, channel, 0))
3864         goto out;
3865     
3866       /* Send the channel key. This sends it to our local clients and if
3867          we are normal server to our router as well. */
3868       silc_server_send_channel_key(server, NULL, channel, 
3869                                    server->server_type == SILC_ROUTER ? 
3870                                    FALSE : !server->standalone);
3871     }
3872   } else {
3873     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3874       /* Cipher mode is unset. Remove the cipher and revert back to 
3875          default cipher */
3876       cipher = channel->cipher;
3877
3878       /* Delete old cipher and allocate default one */
3879       silc_cipher_free(channel->channel_key);
3880       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, 
3881                              &channel->channel_key)) {
3882         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3883                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3884         goto out;
3885       }
3886
3887       /* Re-generate channel key */
3888       if (!silc_server_create_channel_key(server, channel, 0))
3889         goto out;
3890       
3891       /* Send the channel key. This sends it to our local clients and if
3892          we are normal server to our router as well. */
3893       silc_server_send_channel_key(server, NULL, channel, 
3894                                    server->server_type == SILC_ROUTER ? 
3895                                    FALSE : !server->standalone);
3896     }
3897   }
3898
3899   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3900     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3901       /* HMAC to use protect the traffic */
3902       unsigned char hash[32];
3903
3904       /* Get hmac */
3905       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3906       if (!hmac) {
3907         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3908                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3909         goto out;
3910       }
3911
3912       /* Delete old hmac and allocate the new one */
3913       silc_hmac_free(channel->hmac);
3914       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3915         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3917         goto out;
3918       }
3919
3920       /* Set the HMAC key out of current channel key. The client must do
3921          this locally. */
3922       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3923                      channel->key_len / 8, 
3924                      hash);
3925       silc_hmac_set_key(channel->hmac, hash, 
3926                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3927       memset(hash, 0, sizeof(hash));
3928     }
3929   } else {
3930     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3931       /* Hmac mode is unset. Remove the hmac and revert back to 
3932          default hmac */
3933       unsigned char hash[32];
3934       hmac = channel->hmac_name;
3935
3936       /* Delete old hmac and allocate default one */
3937       silc_hmac_free(channel->hmac);
3938       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, 
3939                            &channel->hmac)) {
3940         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3941                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3942         goto out;
3943       }
3944
3945       /* Set the HMAC key out of current channel key. The client must do
3946          this locally. */
3947       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3948                      channel->key_len / 8, 
3949                      hash);
3950       silc_hmac_set_key(channel->hmac, hash, 
3951                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3952       memset(hash, 0, sizeof(hash));
3953     }
3954   }
3955
3956   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3957     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3958       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3959         /* Set the founder authentication */
3960         SilcAuthPayload auth;
3961         
3962         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3963         if (!tmp) {
3964           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3965                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3966           goto out;
3967         }
3968
3969         auth = silc_auth_payload_parse(tmp, tmp_len);
3970         if (!auth) {
3971           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3972                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3973           goto out;
3974         }
3975
3976         /* Save the public key */
3977         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3978         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3979         silc_free(tmp);
3980         
3981         channel->founder_method = silc_auth_get_method(auth);
3982
3983         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3984           tmp = silc_auth_get_data(auth, &tmp_len);
3985           channel->founder_passwd = 
3986             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3987           memcpy(channel->founder_passwd, tmp, tmp_len);
3988           channel->founder_passwd_len = tmp_len;
3989         } else {
3990           /* Verify the payload before setting the mode */
3991           if (!silc_auth_verify(auth, channel->founder_method, 
3992                                 channel->founder_key, 0, idata->hash,
3993                                 client->id, SILC_ID_CLIENT)) {
3994             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995                                                   SILC_STATUS_ERR_AUTH_FAILED);
3996             goto out;
3997           }
3998         }
3999
4000         silc_auth_payload_free(auth);
4001       }
4002     }
4003   } else {
4004     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4005       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4006         if (channel->founder_key)
4007           silc_pkcs_public_key_free(channel->founder_key);
4008         if (channel->founder_passwd) {
4009           silc_free(channel->founder_passwd);
4010           channel->founder_passwd = NULL;
4011         }
4012       }
4013     }
4014   }
4015
4016   /* Finally, set the mode */
4017   channel->mode = mode_mask;
4018
4019   /* Send CMODE_CHANGE notify */
4020   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4021   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4022                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4023                                      cidp->data, cidp->len, 
4024                                      tmp_mask, 4,
4025                                      cipher, cipher ? strlen(cipher) : 0,
4026                                      hmac, hmac ? strlen(hmac) : 0);
4027
4028   /* Set CMODE notify type to network */
4029   if (!server->standalone)
4030     silc_server_send_notify_cmode(server, server->router->connection,
4031                                   server->server_type == SILC_ROUTER ? 
4032                                   TRUE : FALSE, channel,
4033                                   mode_mask, client->id, SILC_ID_CLIENT,
4034                                   cipher, hmac);
4035
4036   /* Send command reply to sender */
4037   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4038                                                 SILC_STATUS_OK, ident, 2,
4039                                                 2, tmp_id, tmp_len2,
4040                                                 3, tmp_mask, 4);
4041   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4042                           packet->data, packet->len, FALSE);
4043     
4044   silc_buffer_free(packet);
4045   silc_free(channel_id);
4046   silc_free(cidp);
4047
4048  out:
4049   silc_server_command_free(cmd);
4050 }
4051
4052 /* Server side of CUMODE command. Changes client's mode on a channel. */
4053
4054 SILC_SERVER_CMD_FUNC(cumode)
4055 {
4056   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4057   SilcServer server = cmd->server;
4058   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4059   SilcIDListData idata = (SilcIDListData)client;
4060   SilcChannelID *channel_id;
4061   SilcClientID *client_id;
4062   SilcChannelEntry channel;
4063   SilcClientEntry target_client;
4064   SilcChannelClientEntry chl;
4065   SilcBuffer packet, idp;
4066   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4067   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4068   int notify = FALSE;
4069   uint16 ident = silc_command_get_ident(cmd->payload);
4070
4071   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4072
4073   /* Get Channel ID */
4074   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4075   if (!tmp_ch_id) {
4076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4077                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4078     goto out;
4079   }
4080   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4081   if (!channel_id) {
4082     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4083                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4084     goto out;
4085   }
4086
4087   /* Get channel entry */
4088   channel = silc_idlist_find_channel_by_id(server->local_list, 
4089                                            channel_id, NULL);
4090   if (!channel) {
4091     channel = silc_idlist_find_channel_by_id(server->global_list, 
4092                                              channel_id, NULL);
4093     if (!channel) {
4094       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4095                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4096       goto out;
4097     }
4098   }
4099
4100   /* Check whether sender is on the channel */
4101   if (!silc_server_client_on_channel(client, channel)) {
4102     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4103                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4104     goto out;
4105   }
4106
4107   /* Check that client has rights to change other's rights */
4108   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4109   sender_mask = chl->mode;
4110   
4111   /* Get the target client's channel mode mask */
4112   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4113   if (!tmp_mask) {
4114     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4115                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4116     goto out;
4117   }
4118   SILC_GET32_MSB(target_mask, tmp_mask);
4119
4120   /* Get target Client ID */
4121   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4122   if (!tmp_id) {
4123     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4124                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4125     goto out;
4126   }
4127   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4128   if (!client_id) {
4129     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4130                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4131     goto out;
4132   }
4133
4134   /* Get target client's entry */
4135   target_client = silc_idlist_find_client_by_id(server->local_list, 
4136                                                 client_id, TRUE, NULL);
4137   if (!target_client) {
4138     target_client = silc_idlist_find_client_by_id(server->global_list, 
4139                                                   client_id, TRUE, NULL);
4140   }
4141
4142   if (target_client != client &&
4143       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4144       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4145     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4146                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4147     goto out;
4148   }
4149
4150   /* Check whether target client is on the channel */
4151   if (target_client != client) {
4152     if (!silc_server_client_on_channel(target_client, channel)) {
4153       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4154                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4155       goto out;
4156     }
4157
4158     /* Get entry to the channel user list */
4159     silc_hash_table_find(channel->user_list, target_client, NULL, 
4160                          (void *)&chl);
4161   }
4162
4163   /* 
4164    * Change the mode 
4165    */
4166
4167   /* If the target client is founder, no one else can change their mode
4168      but themselves. */
4169   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4170     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4171                                           SILC_STATUS_ERR_NOT_YOU);
4172     goto out;
4173   }
4174
4175   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4176     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4177       /* The client tries to claim the founder rights. */
4178       unsigned char *tmp_auth;
4179       uint32 tmp_auth_len, auth_len;
4180       void *auth;
4181       
4182       if (target_client != client) {
4183         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4184                                               SILC_STATUS_ERR_NOT_YOU);
4185         goto out;
4186       }
4187
4188       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4189           !channel->founder_key || !idata->public_key ||
4190           !silc_pkcs_public_key_compare(channel->founder_key, 
4191                                         idata->public_key)) {
4192         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193                                               SILC_STATUS_ERR_NOT_YOU);
4194         goto out;
4195       }
4196
4197       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4198       if (!tmp_auth) {
4199         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4200                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4201         goto out;
4202       }
4203
4204       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4205               (void *)channel->founder_passwd : (void *)channel->founder_key);
4206       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4207                   channel->founder_passwd_len : 0);
4208       
4209       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4210                                  channel->founder_method, auth, auth_len,
4211                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4212         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213                                               SILC_STATUS_ERR_AUTH_FAILED);
4214         goto out;
4215       }
4216       
4217       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4218       notify = TRUE;
4219     }
4220   } else {
4221     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4222       if (target_client == client) {
4223         /* Remove channel founder rights from itself */
4224         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4225         notify = TRUE;
4226       } else {
4227         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228                                               SILC_STATUS_ERR_NOT_YOU);
4229         goto out;
4230       }
4231     }
4232   }
4233
4234   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4235     /* Promote to operator */
4236     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4237       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4238           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4239         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4241         goto out;
4242       }
4243
4244       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4245       notify = TRUE;
4246     }
4247   } else {
4248     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4249       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4250           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4251         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4252                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4253         goto out;
4254       }
4255
4256       /* Demote to normal user */
4257       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4258       notify = TRUE;
4259     }
4260   }
4261
4262   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4263   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4264
4265   /* Send notify to channel, notify only if mode was actually changed. */
4266   if (notify) {
4267     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4268                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4269                                        idp->data, idp->len,
4270                                        tmp_mask, 4, 
4271                                        tmp_id, tmp_len);
4272
4273     /* Set CUMODE notify type to network */
4274     if (!server->standalone)
4275       silc_server_send_notify_cumode(server, server->router->connection,
4276                                      server->server_type == SILC_ROUTER ? 
4277                                      TRUE : FALSE, channel,
4278                                      target_mask, client->id, 
4279                                      SILC_ID_CLIENT,
4280                                      target_client->id);
4281   }
4282
4283   /* Send command reply to sender */
4284   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4285                                                 SILC_STATUS_OK, ident, 3,
4286                                                 2, tmp_mask, 4,
4287                                                 3, tmp_ch_id, tmp_ch_len,
4288                                                 4, tmp_id, tmp_len);
4289   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4290                           packet->data, packet->len, FALSE);
4291     
4292   silc_buffer_free(packet);
4293   silc_free(channel_id);
4294   silc_free(client_id);
4295   silc_buffer_free(idp);
4296
4297  out:
4298   silc_server_command_free(cmd);
4299 }
4300
4301 /* Server side of KICK command. Kicks client out of channel. */
4302
4303 SILC_SERVER_CMD_FUNC(kick)
4304 {
4305   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4306   SilcServer server = cmd->server;
4307   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4308   SilcClientEntry target_client;
4309   SilcChannelID *channel_id;
4310   SilcClientID *client_id;
4311   SilcChannelEntry channel;
4312   SilcChannelClientEntry chl;
4313   SilcBuffer idp;
4314   uint32 tmp_len;
4315   unsigned char *tmp, *comment;
4316
4317   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4318
4319   /* Get Channel ID */
4320   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4321   if (!tmp) {
4322     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4323                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4324     goto out;
4325   }
4326   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4327   if (!channel_id) {
4328     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4329                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4330     goto out;
4331   }
4332
4333   /* Get channel entry */
4334   channel = silc_idlist_find_channel_by_id(server->local_list, 
4335                                            channel_id, NULL);
4336   if (!channel) {
4337     channel = silc_idlist_find_channel_by_id(server->local_list, 
4338                                              channel_id, NULL);
4339     if (!channel) {
4340       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4341                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4342       goto out;
4343     }
4344   }
4345
4346   /* Check whether sender is on the channel */
4347   if (!silc_server_client_on_channel(client, channel)) {
4348     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4349                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4350     goto out;
4351   }
4352
4353   /* Check that the kicker is channel operator or channel founder */
4354   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4355   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4356     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4357                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4358     goto out;
4359   }
4360   
4361   /* Get target Client ID */
4362   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4363   if (!tmp) {
4364     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4365                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4366     goto out;
4367   }
4368   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4369   if (!client_id) {
4370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4371                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4372     goto out;
4373   }
4374
4375   /* Get target client's entry */
4376   target_client = silc_idlist_find_client_by_id(server->local_list, 
4377                                                 client_id, TRUE, NULL);
4378   if (!target_client) {
4379     target_client = silc_idlist_find_client_by_id(server->global_list, 
4380                                                   client_id, TRUE, NULL);
4381   }
4382
4383   /* Check that the target client is not channel founder. Channel founder
4384      cannot be kicked from the channel. */
4385   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4386   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4387     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4388                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4389     goto out;
4390   }
4391   
4392   /* Check whether target client is on the channel */
4393   if (!silc_server_client_on_channel(target_client, channel)) {
4394     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4395                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4396     goto out;
4397   }
4398
4399   /* Get comment */
4400   tmp_len = 0;
4401   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4402   if (tmp_len > 128)
4403     comment = NULL;
4404
4405   /* Send command reply to sender */
4406   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4407                                         SILC_STATUS_OK);
4408
4409   /* Send KICKED notify to local clients on the channel */
4410   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4411   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4412                                      SILC_NOTIFY_TYPE_KICKED, 
4413                                      comment ? 2 : 1,
4414                                      idp->data, idp->len,
4415                                      comment, comment ? strlen(comment) : 0);
4416   silc_buffer_free(idp);
4417
4418   /* Remove the client from the channel. If the channel does not exist
4419      after removing the client then the client kicked itself off the channel
4420      and we don't have to send anything after that. */
4421   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4422                                            target_client, FALSE))
4423     goto out;
4424
4425   /* Send KICKED notify to primary route */
4426   if (!server->standalone)
4427     silc_server_send_notify_kicked(server, server->router->connection,
4428                                    server->server_type == SILC_ROUTER ?
4429                                    TRUE : FALSE, channel,
4430                                    target_client->id, comment);
4431
4432   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4433     /* Re-generate channel key */
4434     if (!silc_server_create_channel_key(server, channel, 0))
4435       goto out;
4436     
4437     /* Send the channel key to the channel. The key of course is not sent
4438        to the client who was kicked off the channel. */
4439     silc_server_send_channel_key(server, target_client->connection, channel, 
4440                                  server->server_type == SILC_ROUTER ? 
4441                                  FALSE : !server->standalone);
4442   }
4443
4444  out:
4445   silc_server_command_free(cmd);
4446 }
4447
4448 /* Server side of OPER command. Client uses this comand to obtain server
4449    operator privileges to this server/router. */
4450
4451 SILC_SERVER_CMD_FUNC(oper)
4452 {
4453   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4454   SilcServer server = cmd->server;
4455   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4456   unsigned char *username, *auth;
4457   uint32 tmp_len;
4458   SilcServerConfigSectionAdminConnection *admin;
4459   SilcIDListData idata = (SilcIDListData)client;
4460
4461   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4462
4463   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4464     goto out;
4465
4466   /* Get the username */
4467   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4468   if (!username) {
4469     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4470                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4471     goto out;
4472   }
4473
4474   /* Get the admin configuration */
4475   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4476                                         username, client->nickname);
4477   if (!admin) {
4478     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4479                                           username, client->nickname);
4480     if (!admin) {
4481       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4482                                             SILC_STATUS_ERR_AUTH_FAILED);
4483       goto out;
4484     }
4485   }
4486
4487   /* Get the authentication payload */
4488   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4489   if (!auth) {
4490     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4491                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4492     goto out;
4493   }
4494
4495   /* Verify the authentication data */
4496   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4497                              admin->auth_data, admin->auth_data_len,
4498                              idata->hash, client->id, SILC_ID_CLIENT)) {
4499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4500                                           SILC_STATUS_ERR_AUTH_FAILED);
4501     goto out;
4502   }
4503
4504   /* Client is now server operator */
4505   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4506
4507   /* Send UMODE change to primary router */
4508   if (!server->standalone)
4509     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4510                                   client->id, client->mode);
4511
4512   /* Send reply to the sender */
4513   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4514                                         SILC_STATUS_OK);
4515
4516  out:
4517   silc_server_command_free(cmd);
4518 }
4519
4520 /* Server side of SILCOPER command. Client uses this comand to obtain router
4521    operator privileges to this router. */
4522
4523 SILC_SERVER_CMD_FUNC(silcoper)
4524 {
4525   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4526   SilcServer server = cmd->server;
4527   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4528   unsigned char *username, *auth;
4529   uint32 tmp_len;
4530   SilcServerConfigSectionAdminConnection *admin;
4531   SilcIDListData idata = (SilcIDListData)client;
4532
4533   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4534
4535   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4536     goto out;
4537
4538   if (server->server_type != SILC_ROUTER) {
4539     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4540                                           SILC_STATUS_ERR_AUTH_FAILED);
4541     goto out;
4542   }
4543
4544   /* Get the username */
4545   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4546   if (!username) {
4547     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4548                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4549     goto out;
4550   }
4551
4552   /* Get the admin configuration */
4553   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4554                                         username, client->nickname);
4555   if (!admin) {
4556     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4557                                           username, client->nickname);
4558     if (!admin) {
4559       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4560                                             SILC_STATUS_ERR_AUTH_FAILED);
4561       goto out;
4562     }
4563   }
4564
4565   /* Get the authentication payload */
4566   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4567   if (!auth) {
4568     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4569                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4570     goto out;
4571   }
4572
4573   /* Verify the authentication data */
4574   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4575                              admin->auth_data, admin->auth_data_len,
4576                              idata->hash, client->id, SILC_ID_CLIENT)) {
4577     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4578                                           SILC_STATUS_ERR_AUTH_FAILED);
4579     goto out;
4580   }
4581
4582   /* Client is now router operator */
4583   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4584
4585   /* Send UMODE change to primary router */
4586   if (!server->standalone)
4587     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4588                                   client->id, client->mode);
4589
4590   /* Send reply to the sender */
4591   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4592                                         SILC_STATUS_OK);
4593
4594  out:
4595   silc_server_command_free(cmd);
4596 }
4597
4598 /* Server side command of CONNECT. Connects us to the specified remote
4599    server or router. */
4600
4601 SILC_SERVER_CMD_FUNC(connect)
4602 {
4603   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4604   SilcServer server = cmd->server;
4605   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4606   unsigned char *tmp, *host;
4607   uint32 tmp_len;
4608   uint32 port = SILC_PORT;
4609
4610   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4611
4612   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4613     goto out;
4614
4615   /* Check whether client has the permissions. */
4616   if (client->mode == SILC_UMODE_NONE) {
4617     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4618                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4619     goto out;
4620   }
4621
4622   if (server->server_type == SILC_ROUTER && 
4623       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4624     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4625                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4626     goto out;
4627   }
4628
4629   /* Get the remote server */
4630   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4631   if (!host) {
4632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4633                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4634     goto out;
4635   }
4636
4637   /* Get port */
4638   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4639   if (tmp)
4640     SILC_GET32_MSB(port, tmp);
4641
4642   /* Create the connection. It is done with timeout and is async. */
4643   silc_server_create_connection(server, host, port);
4644
4645   /* Send reply to the sender */
4646   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4647                                         SILC_STATUS_OK);
4648
4649  out:
4650   silc_server_command_free(cmd);
4651 }
4652
4653 /* Server side of command BAN. This is used to manage the ban list of the
4654    channel. To add clients and remove clients from the ban list. */
4655
4656 SILC_SERVER_CMD_FUNC(ban)
4657 {
4658   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4659   SilcServer server = cmd->server;
4660   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4661   SilcBuffer packet;
4662   SilcChannelEntry channel;
4663   SilcChannelClientEntry chl;
4664   SilcChannelID *channel_id = NULL;
4665   unsigned char *id, *add, *del;
4666   uint32 id_len, tmp_len;
4667   uint16 ident = silc_command_get_ident(cmd->payload);
4668
4669   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4670     goto out;
4671
4672   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4673
4674   /* Get Channel ID */
4675   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4676   if (id) {
4677     channel_id = silc_id_payload_parse_id(id, id_len);
4678     if (!channel_id) {
4679       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4680                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4681       goto out;
4682     }
4683   }
4684
4685   /* Get channel entry. The server must know about the channel since the
4686      client is expected to be on the channel. */
4687   channel = silc_idlist_find_channel_by_id(server->local_list, 
4688                                            channel_id, NULL);
4689   if (!channel) {
4690     channel = silc_idlist_find_channel_by_id(server->global_list, 
4691                                              channel_id, NULL);
4692     if (!channel) {
4693       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4694                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4695       goto out;
4696     }
4697   }
4698
4699   /* Check whether this client is on the channel */
4700   if (!silc_server_client_on_channel(client, channel)) {
4701     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4702                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4703     goto out;
4704   }
4705
4706   /* Get entry to the channel user list */
4707   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4708
4709   /* The client must be at least channel operator. */
4710   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4711     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4712                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4713     goto out;
4714   }
4715
4716   /* Get the new ban and add it to the ban list */
4717   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4718   if (add) {
4719     if (!channel->ban_list)
4720       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4721     else
4722       channel->ban_list = silc_realloc(channel->ban_list, 
4723                                        sizeof(*channel->ban_list) * 
4724                                        (tmp_len + 
4725                                         strlen(channel->ban_list) + 2));
4726     if (add[tmp_len - 1] == ',')
4727       add[tmp_len - 1] = '\0';
4728
4729     strncat(channel->ban_list, add, tmp_len);
4730     strncat(channel->ban_list, ",", 1);
4731   }
4732
4733   /* Get the ban to be removed and remove it from the list */
4734   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4735   if (del && channel->ban_list) {
4736     char *start, *end, *n;
4737
4738     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4739       silc_free(channel->ban_list);
4740       channel->ban_list = NULL;
4741     } else {
4742       start = strstr(channel->ban_list, del);
4743       if (start && strlen(start) >= tmp_len) {
4744         end = start + tmp_len;
4745         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4746         strncat(n, channel->ban_list, start - channel->ban_list);
4747         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4748                              end) - 1);
4749         silc_free(channel->ban_list);
4750         channel->ban_list = n;
4751       }
4752     }
4753   }
4754
4755   /* Send the BAN notify type to our primary router. */
4756   if (!server->standalone && (add || del))
4757     silc_server_send_notify_ban(server, server->router->connection,
4758                                 server->server_type == SILC_ROUTER ?
4759                                 TRUE : FALSE, channel, add, del);
4760
4761   /* Send the reply back to the client */
4762   if (channel->ban_list)
4763     packet = 
4764       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4765                                            SILC_STATUS_OK, ident, 2,
4766                                            2, id, id_len,
4767                                            3, channel->ban_list, 
4768                                            strlen(channel->ban_list) - 1);
4769   else
4770     packet = 
4771       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4772                                            SILC_STATUS_OK, ident, 1,
4773                                            2, id, id_len);
4774
4775   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4776                           packet->data, packet->len, FALSE);
4777     
4778   silc_buffer_free(packet);
4779
4780  out:
4781   silc_free(channel_id);
4782   silc_server_command_free(cmd);
4783 }
4784
4785 /* Server side command of CLOSE. Closes connection to a specified server. */
4786  
4787 SILC_SERVER_CMD_FUNC(close)
4788 {
4789   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4790   SilcServer server = cmd->server;
4791   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4792   SilcServerEntry server_entry;
4793   SilcSocketConnection sock;
4794   unsigned char *tmp;
4795   uint32 tmp_len;
4796   unsigned char *name;
4797   uint32 port = SILC_PORT;
4798
4799   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4800
4801   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4802     goto out;
4803
4804   /* Check whether client has the permissions. */
4805   if (client->mode == SILC_UMODE_NONE) {
4806     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4807                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4808     goto out;
4809   }
4810
4811   /* Get the remote server */
4812   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4813   if (!name) {
4814     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4815                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4816     goto out;
4817   }
4818
4819   /* Get port */
4820   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4821   if (tmp)
4822     SILC_GET32_MSB(port, tmp);
4823
4824   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4825                                                  name, port, FALSE, NULL);
4826   if (!server_entry)
4827     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4828                                                    name, port, FALSE, NULL);
4829   if (!server_entry) {
4830     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4831                                           SILC_STATUS_ERR_NO_SERVER_ID);
4832     goto out;
4833   }
4834
4835   /* Send reply to the sender */
4836   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4837                                         SILC_STATUS_OK);
4838
4839   /* Close the connection to the server */
4840   sock = (SilcSocketConnection)server_entry->connection;
4841
4842   /* If we shutdown primary router connection manually then don't trigger
4843      any reconnect or backup router connections, by setting the router
4844      to NULL here. */
4845   if (server->router == server_entry) {
4846     server->id_entry->router = NULL;
4847     server->router = NULL;
4848     server->standalone = TRUE;
4849   }
4850   silc_server_free_sock_user_data(server, sock);
4851   silc_server_close_connection(server, sock);
4852   
4853  out:
4854   silc_server_command_free(cmd);
4855 }
4856
4857 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4858    active connections. */
4859  
4860 SILC_SERVER_CMD_FUNC(shutdown)
4861 {
4862   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4863   SilcServer server = cmd->server;
4864   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4865
4866   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4867
4868   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4869     goto out;
4870
4871   /* Check whether client has the permission. */
4872   if (client->mode == SILC_UMODE_NONE) {
4873     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4874                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4875     goto out;
4876   }
4877
4878   /* Send reply to the sender */
4879   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4880                                         SILC_STATUS_OK);
4881
4882   /* Then, gracefully, or not, bring the server down. */
4883   silc_server_stop(server);
4884   exit(0);
4885
4886  out:
4887   silc_server_command_free(cmd);
4888 }
4889  
4890 /* Server side command of LEAVE. Removes client from a channel. */
4891
4892 SILC_SERVER_CMD_FUNC(leave)
4893 {
4894   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4895   SilcServer server = cmd->server;
4896   SilcSocketConnection sock = cmd->sock;
4897   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4898   SilcChannelID *id = NULL;
4899   SilcChannelEntry channel;
4900   uint32 len;
4901   unsigned char *tmp;
4902
4903   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4904
4905   /* Get Channel ID */
4906   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4907   if (!tmp) {
4908     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4909                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4910     goto out;
4911   }
4912   id = silc_id_payload_parse_id(tmp, len);
4913   if (!id) {
4914     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4915                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4916     goto out;
4917   }
4918
4919   /* Get channel entry */
4920   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4921   if (!channel) {
4922     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4923     if (!channel) {
4924       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4925                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4926       goto out;
4927     }
4928   }
4929
4930   /* Check whether this client is on the channel */
4931   if (!silc_server_client_on_channel(id_entry, channel)) {
4932     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4933                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4934     goto out;
4935   }
4936
4937   /* Notify routers that they should remove this client from their list
4938      of clients on the channel. Send LEAVE notify type. */
4939   if (!server->standalone)
4940     silc_server_send_notify_leave(server, server->router->connection,
4941                                   server->server_type == SILC_ROUTER ?
4942                                   TRUE : FALSE, channel, id_entry->id);
4943
4944   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4945                                         SILC_STATUS_OK);
4946
4947   /* Remove client from channel */
4948   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4949                                            TRUE))
4950     /* If the channel does not exist anymore we won't send anything */
4951     goto out;
4952
4953   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4954     /* Re-generate channel key */
4955     if (!silc_server_create_channel_key(server, channel, 0))
4956       goto out;
4957
4958     /* Send the channel key */
4959     silc_server_send_channel_key(server, NULL, channel, 
4960                                  server->server_type == SILC_ROUTER ? 
4961                                  FALSE : !server->standalone);
4962   }
4963
4964  out:
4965   silc_free(id);
4966   silc_server_command_free(cmd);
4967 }
4968
4969 /* Server side of command USERS. Resolves clients and their USERS currently
4970    joined on the requested channel. The list of Client ID's and their modes
4971    on the channel is sent back. */
4972
4973 SILC_SERVER_CMD_FUNC(users)
4974 {
4975   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4976   SilcServer server = cmd->server;
4977   SilcChannelEntry channel;
4978   SilcChannelID *id = NULL;
4979   SilcBuffer packet, idp;
4980   unsigned char *channel_id;
4981   uint32 channel_id_len;
4982   SilcBuffer client_id_list;
4983   SilcBuffer client_mode_list;
4984   unsigned char lc[4];
4985   uint32 list_count = 0;
4986   uint16 ident = silc_command_get_ident(cmd->payload);
4987   char *channel_name;
4988
4989   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4990
4991   /* Get Channel ID */
4992   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4993
4994   /* Get channel name */
4995   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4996
4997   if (!channel_id && !channel_name) {
4998     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4999                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5000     goto out;
5001   }
5002
5003   if (channel_id) {
5004     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5005     if (!id) {
5006       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5007                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5008       goto out;
5009     }
5010   }
5011
5012   /* If we are server and we don't know about this channel we will send
5013      the command to our router. If we know about the channel then we also
5014      have the list of users already. */
5015   if (id)
5016     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5017   else
5018     channel = silc_idlist_find_channel_by_name(server->local_list, 
5019                                                channel_name, NULL);
5020
5021   if (!channel || channel->disabled) {
5022     if (server->server_type != SILC_ROUTER && !server->standalone &&
5023         !cmd->pending) {
5024       SilcBuffer tmpbuf;
5025       
5026       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5027       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5028       
5029       /* Send USERS command */
5030       silc_server_packet_send(server, server->router->connection,
5031                               SILC_PACKET_COMMAND, cmd->packet->flags,
5032                               tmpbuf->data, tmpbuf->len, TRUE);
5033       
5034       /* Reprocess this packet after received reply */
5035       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5036                                   silc_command_get_ident(cmd->payload),
5037                                   silc_server_command_destructor,
5038                                   silc_server_command_users,
5039                                   silc_server_command_dup(cmd));
5040       cmd->pending = TRUE;
5041       silc_command_set_ident(cmd->payload, ident);
5042       
5043       silc_buffer_free(tmpbuf);
5044       silc_free(id);
5045       return;
5046     }
5047
5048     /* Check the global list as well. */
5049     if (id)
5050       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5051     else
5052       channel = silc_idlist_find_channel_by_name(server->global_list, 
5053                                                  channel_name, NULL);
5054     if (!channel) {
5055       /* Channel really does not exist */
5056       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5057                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5058       goto out;
5059     }
5060   }
5061
5062   /* If the channel is private or secret do not send anything, unless the
5063      user requesting this command is on the channel. */
5064   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5065     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5066         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5068                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5069       goto out;
5070     }
5071   } else {
5072     if (channel->mode & 
5073         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5074       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5075                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5076       goto out;
5077     }
5078   }
5079
5080   /* Get the users list */
5081   silc_server_get_users_on_channel(server, channel, &client_id_list,
5082                                    &client_mode_list, &list_count);
5083
5084   /* List count */
5085   SILC_PUT32_MSB(list_count, lc);
5086
5087   /* Send reply */
5088   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5089   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5090                                                 SILC_STATUS_OK, ident, 4,
5091                                                 2, idp->data, idp->len,
5092                                                 3, lc, 4,
5093                                                 4, client_id_list->data,
5094                                                 client_id_list->len,
5095                                                 5, client_mode_list->data,
5096                                                 client_mode_list->len);
5097   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5098                           packet->data, packet->len, FALSE);
5099     
5100   silc_buffer_free(idp);
5101   silc_buffer_free(packet);
5102   silc_buffer_free(client_id_list);
5103   silc_buffer_free(client_mode_list);
5104   silc_free(id);
5105
5106  out:
5107   silc_server_command_free(cmd);
5108 }
5109
5110 /* Server side of command GETKEY. This fetches the client's public key
5111    from the server where to the client is connected. */
5112
5113 SILC_SERVER_CMD_FUNC(getkey)
5114 {
5115   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5116   SilcServer server = cmd->server;
5117   SilcBuffer packet;
5118   SilcClientEntry client;
5119   SilcServerEntry server_entry;
5120   SilcClientID *client_id = NULL;
5121   SilcServerID *server_id = NULL;
5122   SilcIDPayload idp = NULL;
5123   uint16 ident = silc_command_get_ident(cmd->payload);
5124   unsigned char *tmp, *pkdata;
5125   uint32 tmp_len, pklen;
5126   SilcBuffer pk = NULL;
5127   SilcIdType id_type;
5128
5129   SILC_LOG_DEBUG(("Start"));
5130
5131   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5132   if (!tmp) {
5133     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5134                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5135     goto out;
5136   }
5137   idp = silc_id_payload_parse_data(tmp, tmp_len);
5138   if (!idp) {
5139     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5140                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5141     goto out;
5142   }
5143
5144   id_type = silc_id_payload_get_type(idp);
5145   if (id_type == SILC_ID_CLIENT) {
5146     client_id = silc_id_payload_get_id(idp);
5147
5148     /* If the client is not found from local list there is no chance it
5149        would be locally connected client so send the command further. */
5150     client = silc_idlist_find_client_by_id(server->local_list, 
5151                                            client_id, TRUE, NULL);
5152     if (!client)
5153       client = silc_idlist_find_client_by_id(server->global_list, 
5154                                              client_id, TRUE, NULL);
5155     
5156     if ((!client && !cmd->pending && !server->standalone) ||
5157         (client && !client->connection && !cmd->pending) ||
5158         (client && !client->data.public_key && !cmd->pending)) {
5159       SilcBuffer tmpbuf;
5160       uint16 old_ident;
5161       SilcSocketConnection dest_sock;
5162       
5163       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5164                                                client_id, NULL);
5165       if (!dest_sock)
5166         goto out;
5167       
5168       old_ident = silc_command_get_ident(cmd->payload);
5169       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5170       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5171       
5172       silc_server_packet_send(server, dest_sock,
5173                               SILC_PACKET_COMMAND, cmd->packet->flags,
5174                               tmpbuf->data, tmpbuf->len, TRUE);
5175       
5176       /* Reprocess this packet after received reply from router */
5177       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5178                                   silc_command_get_ident(cmd->payload),
5179                                   silc_server_command_destructor,
5180                                   silc_server_command_getkey,
5181                                   silc_server_command_dup(cmd));
5182       cmd->pending = TRUE;
5183       
5184       silc_command_set_ident(cmd->payload, old_ident);
5185       silc_buffer_free(tmpbuf);
5186       return;
5187     }
5188
5189     if (!client) {
5190       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5191                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5192       goto out;
5193     }
5194
5195     /* The client is locally connected, just get the public key and
5196        send it back. If they key does not exist then do not send it, 
5197        send just OK reply */
5198     if (!client->data.public_key) {
5199       pkdata = NULL;
5200       pklen = 0;
5201     } else {
5202       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5203       pk = silc_buffer_alloc(4 + tmp_len);
5204       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5205       silc_buffer_format(pk,
5206                          SILC_STR_UI_SHORT(tmp_len),
5207                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5208                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5209                          SILC_STR_END);
5210       silc_free(tmp);
5211       pkdata = pk->data;
5212       pklen = pk->len;
5213     }
5214   } else if (id_type == SILC_ID_SERVER) {
5215     server_id = silc_id_payload_get_id(idp);
5216
5217     /* If the server is not found from local list there is no chance it
5218        would be locally connected server so send the command further. */
5219     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5220                                                  server_id, TRUE, NULL);
5221     if (!server_entry)
5222       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5223                                                    server_id, TRUE, NULL);
5224     
5225     if (server_entry != server->id_entry &&
5226         ((!server_entry && !cmd->pending && !server->standalone) ||
5227          (server_entry && !server_entry->connection && !cmd->pending &&
5228           !server->standalone) ||
5229          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5230           !server->standalone))) {
5231       SilcBuffer tmpbuf;
5232       uint16 old_ident;
5233       
5234       old_ident = silc_command_get_ident(cmd->payload);
5235       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5236       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5237       
5238       silc_server_packet_send(server, server->router->connection,
5239                               SILC_PACKET_COMMAND, cmd->packet->flags,
5240                               tmpbuf->data, tmpbuf->len, TRUE);
5241       
5242       /* Reprocess this packet after received reply from router */
5243       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5244                                   silc_command_get_ident(cmd->payload),
5245                                   silc_server_command_destructor,
5246                                   silc_server_command_getkey,
5247                                   silc_server_command_dup(cmd));
5248       cmd->pending = TRUE;
5249       
5250       silc_command_set_ident(cmd->payload, old_ident);
5251       silc_buffer_free(tmpbuf);
5252       return;
5253     }
5254
5255     if (!server_entry) {
5256       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5257                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5258       goto out;
5259     }
5260
5261     /* If they key does not exist then do not send it, send just OK reply */
5262     if (!server_entry->data.public_key) {
5263       pkdata = NULL;
5264       pklen = 0;
5265     } else {
5266       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5267                                         &tmp_len);
5268       pk = silc_buffer_alloc(4 + tmp_len);
5269       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5270       silc_buffer_format(pk,
5271                          SILC_STR_UI_SHORT(tmp_len),
5272                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5273                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5274                          SILC_STR_END);
5275       silc_free(tmp);
5276       pkdata = pk->data;
5277       pklen = pk->len;
5278     }
5279   } else {
5280     goto out;
5281   }
5282
5283   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5284   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5285                                                 SILC_STATUS_OK, ident, 
5286                                                 pkdata ? 2 : 1,
5287                                                 2, tmp, tmp_len,
5288                                                 3, pkdata, pklen);
5289   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5290                           packet->data, packet->len, FALSE);
5291   silc_buffer_free(packet);
5292
5293   if (pk)
5294     silc_buffer_free(pk);
5295
5296  out:
5297   if (idp)
5298     silc_id_payload_free(idp);
5299   silc_free(client_id);
5300   silc_free(server_id);
5301   silc_server_command_free(cmd);
5302 }